1 //===-- Unittests for sscanf ----------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "src/stdio/vsscanf.h" 10 11 #include "test/UnitTest/Test.h" 12 13 int call_vsscanf(const char *__restrict buffer, const char *__restrict format, 14 ...) { 15 va_list vlist; 16 va_start(vlist, format); 17 int ret = LIBC_NAMESPACE::vsscanf(buffer, format, vlist); 18 va_end(vlist); 19 return ret; 20 } 21 22 TEST(LlvmLibcVSScanfTest, SimpleStringConv) { 23 int ret_val; 24 char buffer[10]; 25 char buffer2[10]; 26 ret_val = call_vsscanf("abc123", "abc %s", buffer); 27 ASSERT_EQ(ret_val, 1); 28 ASSERT_STREQ(buffer, "123"); 29 30 ret_val = call_vsscanf("abc123", "%3s %3s", buffer, buffer2); 31 ASSERT_EQ(ret_val, 2); 32 ASSERT_STREQ(buffer, "abc"); 33 ASSERT_STREQ(buffer2, "123"); 34 35 ret_val = call_vsscanf("abc 123", "%3s%3s", buffer, buffer2); 36 ASSERT_EQ(ret_val, 2); 37 ASSERT_STREQ(buffer, "abc"); 38 ASSERT_STREQ(buffer2, "123"); 39 } 40 41 TEST(LlvmLibcVSScanfTest, IntConvSimple) { 42 int ret_val; 43 int result = 0; 44 ret_val = call_vsscanf("123", "%d", &result); 45 EXPECT_EQ(ret_val, 1); 46 EXPECT_EQ(result, 123); 47 48 ret_val = call_vsscanf("456", "%i", &result); 49 EXPECT_EQ(ret_val, 1); 50 EXPECT_EQ(result, 456); 51 52 ret_val = call_vsscanf("789", "%x", &result); 53 EXPECT_EQ(ret_val, 1); 54 EXPECT_EQ(result, 0x789); 55 56 ret_val = call_vsscanf("012", "%o", &result); 57 EXPECT_EQ(ret_val, 1); 58 EXPECT_EQ(result, 012); 59 60 ret_val = call_vsscanf("345", "%u", &result); 61 EXPECT_EQ(ret_val, 1); 62 EXPECT_EQ(result, 345); 63 64 // 288 characters 65 ret_val = call_vsscanf("10000000000000000000000000000000" 66 "00000000000000000000000000000000" 67 "00000000000000000000000000000000" 68 "00000000000000000000000000000000" 69 "00000000000000000000000000000000" 70 "00000000000000000000000000000000" 71 "00000000000000000000000000000000" 72 "00000000000000000000000000000000" 73 "00000000000000000000000000000000", 74 "%d", &result); 75 EXPECT_EQ(ret_val, 1); 76 EXPECT_EQ(result, int(LIBC_NAMESPACE::cpp::numeric_limits<intmax_t>::max())); 77 78 ret_val = call_vsscanf("Not an integer", "%d", &result); 79 EXPECT_EQ(ret_val, 0); 80 } 81 82 TEST(LlvmLibcVSScanfTest, IntConvLengthModifier) { 83 int ret_val; 84 uintmax_t max_result = 0; 85 int int_result = 0; 86 char char_result = 0; 87 88 ret_val = call_vsscanf("123", "%ju", &max_result); 89 EXPECT_EQ(ret_val, 1); 90 EXPECT_EQ(max_result, uintmax_t(123)); 91 92 // Check overflow handling 93 ret_val = 94 call_vsscanf("999999999999999999999999999999999999", "%ju", &max_result); 95 EXPECT_EQ(ret_val, 1); 96 EXPECT_EQ(max_result, LIBC_NAMESPACE::cpp::numeric_limits<uintmax_t>::max()); 97 98 // Because this is unsigned, any out of range value should return the maximum, 99 // even with a negative sign. 100 ret_val = 101 call_vsscanf("-999999999999999999999999999999999999", "%ju", &max_result); 102 EXPECT_EQ(ret_val, 1); 103 EXPECT_EQ(max_result, LIBC_NAMESPACE::cpp::numeric_limits<uintmax_t>::max()); 104 105 ret_val = call_vsscanf("-18446744073709551616", "%ju", &max_result); 106 EXPECT_EQ(ret_val, 1); 107 EXPECT_EQ(max_result, LIBC_NAMESPACE::cpp::numeric_limits<uintmax_t>::max()); 108 109 // But any number below the maximum should have the - sign applied. 110 ret_val = call_vsscanf("-1", "%ju", &max_result); 111 EXPECT_EQ(ret_val, 1); 112 EXPECT_EQ(max_result, uintmax_t(-1)); 113 114 ret_val = call_vsscanf("-1", "%u", &int_result); 115 EXPECT_EQ(ret_val, 1); 116 EXPECT_EQ(int_result, -1); 117 118 max_result = 0xff00ff00ff00ff00; 119 char_result = 0x6f; 120 121 // Overflows for sizes larger than the maximum are handled by casting. 122 ret_val = call_vsscanf("8589967360", "%d", &int_result); 123 EXPECT_EQ(ret_val, 1); 124 EXPECT_EQ(int_result, int(8589967360)); // 2^33 + 2^15 125 126 // Check that the adjacent values weren't touched by the overflow. 127 ASSERT_EQ(max_result, uintmax_t(0xff00ff00ff00ff00)); 128 ASSERT_EQ(char_result, char(0x6f)); 129 130 ret_val = call_vsscanf("-8589967360", "%d", &int_result); 131 EXPECT_EQ(ret_val, 1); 132 EXPECT_EQ(int_result, int(-8589967360)); 133 ASSERT_EQ(max_result, uintmax_t(0xff00ff00ff00ff00)); 134 ASSERT_EQ(char_result, char(0x6f)); 135 136 ret_val = call_vsscanf("25", "%hhd", &char_result); 137 EXPECT_EQ(ret_val, 1); 138 EXPECT_EQ(char_result, char(25)); 139 } 140 141 TEST(LlvmLibcVSScanfTest, IntConvBaseSelection) { 142 int ret_val; 143 int result = 0; 144 ret_val = call_vsscanf("0xabc123", "%i", &result); 145 EXPECT_EQ(ret_val, 1); 146 EXPECT_EQ(result, 0xabc123); 147 148 ret_val = call_vsscanf("0456", "%i", &result); 149 EXPECT_EQ(ret_val, 1); 150 EXPECT_EQ(result, 0456); 151 152 ret_val = call_vsscanf("0999", "%i", &result); 153 EXPECT_EQ(ret_val, 1); 154 EXPECT_EQ(result, 0); 155 156 ret_val = call_vsscanf("123abc456", "%i", &result); 157 EXPECT_EQ(ret_val, 1); 158 EXPECT_EQ(result, 123); 159 } 160