|
22 | 22 | #include <gtest/gtest.h> |
23 | 23 |
|
24 | 24 | #include <limits> |
| 25 | +#include <memory> |
25 | 26 |
|
26 | 27 | #include "arrow/util/logging.h" |
27 | 28 | #include "gandiva/execution_context.h" |
@@ -649,6 +650,20 @@ TEST(TestGdvFnStubs, TestUpper) { |
649 | 650 |
|
650 | 651 | ctx.Reset(); |
651 | 652 |
|
| 653 | + // Truncated trailing multibyte glyph in an exact-sized buffer (no trailing NUL); |
| 654 | + // the lead byte claims more bytes than remain. Use new[] so the over-read trips |
| 655 | + // ASAN instead of landing on std::string's guaranteed terminator. |
| 656 | + { |
| 657 | + const int32_t trunc_len = 4; |
| 658 | + std::unique_ptr<char[]> trunc(new char[trunc_len]{'a', 'b', 'c', '\xc3'}); |
| 659 | + out_str = gdv_fn_upper_utf8(ctx_ptr, trunc.get(), trunc_len, &out_len); |
| 660 | + EXPECT_EQ(out_len, 0); |
| 661 | + EXPECT_THAT(ctx.get_error(), |
| 662 | + ::testing::HasSubstr( |
| 663 | + "unexpected byte \\c3 encountered while decoding utf8 string")); |
| 664 | + ctx.Reset(); |
| 665 | + } |
| 666 | + |
652 | 667 | // Max Len Test |
653 | 668 | out_len = -1; |
654 | 669 | int32_t bad_len = std::numeric_limits<int32_t>::max() / 2 + 1; |
@@ -752,6 +767,19 @@ TEST(TestGdvFnStubs, TestLower) { |
752 | 767 | "unexpected byte \\c3 encountered while decoding utf8 string")); |
753 | 768 | ctx.Reset(); |
754 | 769 |
|
| 770 | + // Truncated trailing 3-byte lead in an exact-sized buffer (no trailing NUL); only |
| 771 | + // the lead byte is present, so decoding must not read the missing continuation bytes. |
| 772 | + { |
| 773 | + const int32_t trunc_len = 4; |
| 774 | + std::unique_ptr<char[]> trunc(new char[trunc_len]{'a', 'b', 'c', '\xe0'}); |
| 775 | + out_str = gdv_fn_lower_utf8(ctx_ptr, trunc.get(), trunc_len, &out_len); |
| 776 | + EXPECT_EQ(out_len, 0); |
| 777 | + EXPECT_THAT(ctx.get_error(), |
| 778 | + ::testing::HasSubstr( |
| 779 | + "unexpected byte \\e0 encountered while decoding utf8 string")); |
| 780 | + ctx.Reset(); |
| 781 | + } |
| 782 | + |
755 | 783 | std::string e( |
756 | 784 | "åbÑg\xe0\xa0" |
757 | 785 | "åBUå"); |
@@ -805,7 +833,7 @@ TEST(TestGdvFnStubs, TestInitCap) { |
805 | 833 | EXPECT_EQ(std::string(out_str, out_len), "{Õhp,Pqśv}Ń+"); |
806 | 834 | EXPECT_FALSE(ctx.has_error()); |
807 | 835 |
|
808 | | - out_str = gdv_fn_initcap_utf8(ctx_ptr, "sɦasasdsɦsd\"sdsdɦ", 19, &out_len); |
| 836 | + out_str = gdv_fn_initcap_utf8(ctx_ptr, "sɦasasdsɦsd\"sdsdɦ", 20, &out_len); |
809 | 837 | EXPECT_EQ(std::string(out_str, out_len), "Sɦasasdsɦsd\"Sdsdɦ"); |
810 | 838 | EXPECT_FALSE(ctx.has_error()); |
811 | 839 |
|
@@ -842,6 +870,19 @@ TEST(TestGdvFnStubs, TestInitCap) { |
842 | 870 | "unexpected byte \\c3 encountered while decoding utf8 string")); |
843 | 871 | ctx.Reset(); |
844 | 872 |
|
| 873 | + // Truncated trailing multibyte glyph in an exact-sized buffer (no trailing NUL); |
| 874 | + // the lead byte claims more bytes than remain and must not be decoded past the end. |
| 875 | + { |
| 876 | + const int32_t trunc_len = 4; |
| 877 | + std::unique_ptr<char[]> trunc(new char[trunc_len]{'a', 'b', 'c', '\xc3'}); |
| 878 | + out_str = gdv_fn_initcap_utf8(ctx_ptr, trunc.get(), trunc_len, &out_len); |
| 879 | + EXPECT_EQ(out_len, 0); |
| 880 | + EXPECT_THAT(ctx.get_error(), |
| 881 | + ::testing::HasSubstr( |
| 882 | + "unexpected byte \\c3 encountered while decoding utf8 string")); |
| 883 | + ctx.Reset(); |
| 884 | + } |
| 885 | + |
845 | 886 | // Max Len Test |
846 | 887 | out_len = -1; |
847 | 888 | int32_t bad_len = std::numeric_limits<int32_t>::max() / 2 + 1; |
|
0 commit comments