• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <math.h>
6 
7 #include <iterator>
8 #include <limits>
9 
10 #include "build/build_config.h"
11 #include "core/fxcrt/compiler_specific.h"
12 #include "core/fxcrt/fx_string.h"
13 #include "core/fxcrt/fx_system.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 // Unit test covering cases where PDFium replaces well-known library
17 // functionality on any given platformn.
18 
19 #if !BUILDFLAG(IS_WIN)
20 
21 namespace {
22 
23 const char kSentinel = 0x7f;
24 
Check32BitBase16Itoa(int32_t input,const char * expected_output)25 void Check32BitBase16Itoa(int32_t input, const char* expected_output) {
26   const size_t kBufLen = 11;  // "-" + 8 digits + NUL + sentinel.
27   char buf[kBufLen];
28   UNSAFE_TODO({
29     buf[kBufLen - 1] = kSentinel;
30     FXSYS_itoa(input, buf, 16);
31     EXPECT_STREQ(expected_output, buf);
32     EXPECT_EQ(kSentinel, buf[kBufLen - 1]);
33   });
34 }
35 
Check32BitBase10Itoa(int32_t input,const char * expected_output)36 void Check32BitBase10Itoa(int32_t input, const char* expected_output) {
37   const size_t kBufLen = 13;  // "-" + 10 digits + NUL + sentinel.
38   char buf[kBufLen];
39   UNSAFE_TODO({
40     buf[kBufLen - 1] = kSentinel;
41     FXSYS_itoa(input, buf, 10);
42     EXPECT_STREQ(expected_output, buf);
43     EXPECT_EQ(kSentinel, buf[kBufLen - 1]);
44   });
45 }
46 
Check32BitBase2Itoa(int32_t input,const char * expected_output)47 void Check32BitBase2Itoa(int32_t input, const char* expected_output) {
48   const size_t kBufLen = 35;  // "-" + 32 digits + NUL + sentinel.
49   char buf[kBufLen];
50   UNSAFE_TODO({
51     buf[kBufLen - 1] = kSentinel;
52     FXSYS_itoa(input, buf, 2);
53     EXPECT_STREQ(expected_output, buf);
54     EXPECT_EQ(kSentinel, buf[kBufLen - 1]);
55   });
56 }
57 
Check64BitBase16Itoa(int64_t input,const char * expected_output)58 void Check64BitBase16Itoa(int64_t input, const char* expected_output) {
59   const size_t kBufLen = 19;  // "-" + 16 digits + NUL + sentinel.
60   char buf[kBufLen];
61   UNSAFE_TODO({
62     buf[kBufLen - 1] = kSentinel;
63     FXSYS_i64toa(input, buf, 16);
64     EXPECT_STREQ(expected_output, buf);
65     EXPECT_EQ(kSentinel, buf[kBufLen - 1]);
66   });
67 }
68 
Check64BitBase10Itoa(int64_t input,const char * expected_output)69 void Check64BitBase10Itoa(int64_t input, const char* expected_output) {
70   const size_t kBufLen = 22;  // "-" + 19 digits + NUL + sentinel.
71   char buf[kBufLen];
72   UNSAFE_TODO({
73     buf[kBufLen - 1] = kSentinel;
74     FXSYS_i64toa(input, buf, 10);
75     EXPECT_STREQ(expected_output, buf);
76     EXPECT_EQ(kSentinel, buf[kBufLen - 1]);
77   });
78 }
79 
Check64BitBase2Itoa(int64_t input,const char * expected_output)80 void Check64BitBase2Itoa(int64_t input, const char* expected_output) {
81   const size_t kBufLen = 67;  // "-" + 64 digits + NUL + sentinel.
82   char buf[kBufLen];
83   UNSAFE_TODO({
84     buf[kBufLen - 1] = kSentinel;
85     FXSYS_i64toa(input, buf, 2);
86     EXPECT_STREQ(expected_output, buf);
87     EXPECT_EQ(kSentinel, buf[kBufLen - 1]);
88   });
89 }
90 
91 }  // namespace
92 
TEST(fxcrt,FXSYSroundf)93 TEST(fxcrt, FXSYSroundf) {
94   EXPECT_EQ(0, FXSYS_roundf(0.0f));
95   EXPECT_EQ(0, FXSYS_roundf(-0.0f));
96   EXPECT_EQ(0, FXSYS_roundf(0.00001f));
97   EXPECT_EQ(0, FXSYS_roundf(-0.00001f));
98   EXPECT_EQ(3, FXSYS_roundf(3.14159f));
99   EXPECT_EQ(4, FXSYS_roundf(3.5f));
100 
101   // Check for smallest non-zero float values.
102   EXPECT_EQ(0, FXSYS_roundf(std::numeric_limits<float>::min()));
103   EXPECT_EQ(0, FXSYS_roundf(-std::numeric_limits<float>::min()));
104 
105   // Function is a wrapper around standard C library function round(), so
106   // returns the integral value that is nearest to x, with halfway cases
107   // rounded away from zero.
108   EXPECT_EQ(-3, FXSYS_roundf(-3.14159f));
109   EXPECT_EQ(-4, FXSYS_roundf(-3.5f));
110 
111   // Positive rounding stops at maximum int.
112   // MAX_INT=0x7FFFFFFF=2147483647=2.147483647e+9
113   // In IEEE-754 format, 2^31 yields exponent of 0x9E with mantissa of all
114   // zeroes which is 0x4f000000=2.14748365e+9, which is beyond max integer.
115   // Going to next smallest float by minus one from exponent and mantissa of
116   // all ones yields binary float representation of 0x4EFFFFFF=2.14748352e+9,
117   // which is 2147483520.
118   EXPECT_EQ(2147483520, FXSYS_roundf(2.14748352e+9f));
119 
120   // Using a slightly larger value, expect to see it be capped at MAX_INT.
121   EXPECT_EQ(2147483647, FXSYS_roundf(2.14748365e+9f));
122 
123   EXPECT_EQ(2147483647, FXSYS_roundf(2.14748365e+10f));
124   EXPECT_EQ(2147483647, FXSYS_roundf(std::numeric_limits<float>::max()));
125 
126   // Negative rounding stops at minimum int.
127   // MIN_INT=0x80000000=-2147483648,=-2.147483648e+9
128   // In IEEE-754 format, 2^31 yields exponent of 0x9E with mantissa of all
129   // zeroes which is 0x4f000000=2.14748365e+9, and the sign bit set, which
130   // is 0xCF000000 and exactly matches the minimum integer.  Going to next
131   // smallest negative float by minus one from exponent and mantissa of all
132   // ones yields binary float representation of 0xCEFFFFFF=-2.14748352e+9,
133   // which is -2147483520.
134   EXPECT_EQ(-2147483648, FXSYS_roundf(-2.147483648e+10f));
135   EXPECT_EQ(-2147483648, FXSYS_roundf(-2.147483648e+9f));
136   EXPECT_EQ(-2147483520, FXSYS_roundf(-2.14748352e+9f));
137   EXPECT_EQ(-2147483648, FXSYS_roundf(-std::numeric_limits<float>::max()));
138 
139   // NaN should give zero.
140   EXPECT_EQ(0, FXSYS_roundf(NAN));
141 }
142 
TEST(fxcrt,FXSYSround)143 TEST(fxcrt, FXSYSround) {
144   EXPECT_EQ(0, FXSYS_round(0.0));
145   EXPECT_EQ(0, FXSYS_round(-0.0));
146   EXPECT_EQ(0, FXSYS_round(0.00001));
147   EXPECT_EQ(0, FXSYS_round(-0.00001));
148   EXPECT_EQ(3, FXSYS_round(3.14159));
149   EXPECT_EQ(4, FXSYS_round(3.5));
150 
151   // Check for smallest non-zero double values.
152   EXPECT_EQ(0, FXSYS_round(std::numeric_limits<double>::min()));
153   EXPECT_EQ(0, FXSYS_round(-std::numeric_limits<double>::min()));
154 
155   // Function is a wrapper around standard C library function round(), so
156   // returns the integral value that is nearest to x, with halfway cases
157   // rounded away from zero.
158   EXPECT_EQ(-3, FXSYS_round(-3.14159));
159   EXPECT_EQ(-4, FXSYS_round(-3.5));
160 
161   // Positive rounding stops at maximum int.
162   // MAX_INT=0x7FFFFFFF=2147483647=2.147483647e+9
163   // In IEEE-754 double precision format, 2^31 yields exponent of 0x41E with
164   // mantissa of all zeroes which is 0x41E0000000000000=2.14748365e+9, which
165   // is beyond max integer.
166   // Going to next smallest float by minus one from exponent and mantissa of
167   // all ones yields binary float representation of
168   // 41DFFFFFFFC00000=2.147483647e+9, which matches the max integer.
169   EXPECT_EQ(2147483647, FXSYS_round(2.147483647e+9));
170 
171   // Using a slightly larger value, expect to see it be capped at MAX_INT.
172   EXPECT_EQ(2147483647, FXSYS_round(2.14748365e+9));
173 
174   EXPECT_EQ(2147483647, FXSYS_round(2.14748365e+10));
175   EXPECT_EQ(2147483647, FXSYS_round(std::numeric_limits<double>::max()));
176 
177   // Negative rounding stops at minimum int.
178   // MIN_INT=0x80000000=-2147483648,=-2.147483648e+9
179   // In IEEE-754 double precision format, 2^31 yields exponent of 0x41E with
180   // mantissa of all zeroes which is 0x41E0000000000000=2.14748365e+9, and the
181   // sign bit set, which is 0xC1E0000000000000 and exactly matches the minimum
182   // integer.  Going to next smallest negative double by minus one from
183   // exponent and mantissa of all ones yields binary float representation of
184   // 0xC1DFFFFFFFFFFFFF=-2.1474836479999998e+9, which is -2147483648.
185   EXPECT_EQ(-2147483648, FXSYS_round(-2.1474836479999998e+9));
186   EXPECT_EQ(-2147483648, FXSYS_round(-2.147483648e+9));
187   EXPECT_EQ(-2147483648, FXSYS_round(-2.147483648e+10));
188   EXPECT_EQ(-2147483648, FXSYS_round(-std::numeric_limits<double>::max()));
189 
190   // NaN should give zero.
191   EXPECT_EQ(0, FXSYS_round(NAN));
192 }
193 
TEST(fxcrt,FXSYSitoaInvalidRadix)194 TEST(fxcrt, FXSYSitoaInvalidRadix) {
195   char buf[32];
196 
197   FXSYS_itoa(42, buf, 17);  // Ours stops at 16.
198   EXPECT_STREQ("", buf);
199 
200   FXSYS_itoa(42, buf, 1);
201   EXPECT_STREQ("", buf);
202 
203   FXSYS_itoa(42, buf, 0);
204   EXPECT_STREQ("", buf);
205 
206   FXSYS_itoa(42, buf, -1);
207   EXPECT_STREQ("", buf);
208 }
209 
TEST(fxcrt,FXSYSitoa)210 TEST(fxcrt, FXSYSitoa) {
211   Check32BitBase16Itoa(std::numeric_limits<int32_t>::min(), "-80000000");
212   Check32BitBase10Itoa(std::numeric_limits<int32_t>::min(), "-2147483648");
213   Check32BitBase2Itoa(std::numeric_limits<int32_t>::min(),
214                       "-10000000000000000000000000000000");
215 
216   Check32BitBase16Itoa(-1, "-1");
217   Check32BitBase10Itoa(-1, "-1");
218   Check32BitBase2Itoa(-1, "-1");
219 
220   Check32BitBase16Itoa(0, "0");
221   Check32BitBase10Itoa(0, "0");
222   Check32BitBase2Itoa(0, "0");
223 
224   Check32BitBase16Itoa(42, "2a");
225   Check32BitBase10Itoa(42, "42");
226   Check32BitBase2Itoa(42, "101010");
227 
228   Check32BitBase16Itoa(std::numeric_limits<int32_t>::max(), "7fffffff");
229   Check32BitBase10Itoa(std::numeric_limits<int32_t>::max(), "2147483647");
230   Check32BitBase2Itoa(std::numeric_limits<int32_t>::max(),
231                       "1111111111111111111111111111111");
232 }
233 
TEST(fxcrt,FXSYSi64toaInvalidRadix)234 TEST(fxcrt, FXSYSi64toaInvalidRadix) {
235   char buf[32];
236 
237   FXSYS_i64toa(42, buf, 17);  // Ours stops at 16.
238   EXPECT_STREQ("", buf);
239 
240   FXSYS_i64toa(42, buf, 1);
241   EXPECT_STREQ("", buf);
242 
243   FXSYS_i64toa(42, buf, 0);
244   EXPECT_STREQ("", buf);
245 
246   FXSYS_i64toa(42, buf, -1);
247   EXPECT_STREQ("", buf);
248 }
249 
TEST(fxcrt,FXSYSi64toa)250 TEST(fxcrt, FXSYSi64toa) {
251   Check64BitBase16Itoa(std::numeric_limits<int64_t>::min(),
252                        "-8000000000000000");
253   Check64BitBase10Itoa(std::numeric_limits<int64_t>::min(),
254                        "-9223372036854775808");
255   Check64BitBase2Itoa(
256       std::numeric_limits<int64_t>::min(),
257       "-1000000000000000000000000000000000000000000000000000000000000000");
258 
259   Check64BitBase16Itoa(-1, "-1");
260   Check64BitBase10Itoa(-1, "-1");
261   Check64BitBase2Itoa(-1, "-1");
262 
263   Check64BitBase16Itoa(0, "0");
264   Check64BitBase10Itoa(0, "0");
265   Check64BitBase2Itoa(0, "0");
266 
267   Check64BitBase16Itoa(42, "2a");
268   Check64BitBase10Itoa(42, "42");
269   Check64BitBase2Itoa(42, "101010");
270 
271   Check64BitBase16Itoa(std::numeric_limits<int64_t>::max(), "7fffffffffffffff");
272   Check64BitBase10Itoa(std::numeric_limits<int64_t>::max(),
273                        "9223372036854775807");
274   Check64BitBase2Itoa(
275       std::numeric_limits<int64_t>::max(),
276       "111111111111111111111111111111111111111111111111111111111111111");
277 }
278 
279 #endif  // !BUILDFLAG(IS_WIN)
280 
TEST(fxcrt,FXSYSwcsftime)281 TEST(fxcrt, FXSYSwcsftime) {
282   struct tm good_time = {};
283   good_time.tm_year = 74;  // 1900-based.
284   good_time.tm_mon = 7;    // 0-based.
285   good_time.tm_mday = 9;   // 1-based.
286   good_time.tm_hour = 11;
287   good_time.tm_min = 59;
288   good_time.tm_sec = 59;
289 
290   wchar_t buf[100] = {};
291   EXPECT_EQ(19u, UNSAFE_TODO(FXSYS_wcsftime(buf, std::size(buf),
292                                             L"%Y-%m-%dT%H:%M:%S", &good_time)));
293   EXPECT_STREQ(L"1974-08-09T11:59:59", buf);
294 
295   // Ensure wcsftime handles a wide range of years without crashing.
296   struct tm year_time = {};
297   year_time.tm_mon = 7;   // 0-based.
298   year_time.tm_mday = 9;  // 1-based.
299   year_time.tm_hour = 11;
300   year_time.tm_min = 59;
301   year_time.tm_sec = 59;
302 
303   for (int year = -2500; year <= 8500; ++year) {
304     year_time.tm_year = year;
305     wchar_t year_buf[100] = {};
306     UNSAFE_TODO(FXSYS_wcsftime(year_buf, std::size(year_buf),
307                                L"%Y-%m-%dT%H:%M:%S", &year_time));
308   }
309 
310   // Ensure wcsftime handles bad years, etc. without crashing.
311   struct tm bad_time = {};
312   bad_time.tm_year = -1;
313   bad_time.tm_mon = -1;
314   bad_time.tm_mday = -1;
315   bad_time.tm_hour = -1;
316   bad_time.tm_min = -1;
317   bad_time.tm_sec = -1;
318 
319   UNSAFE_TODO(
320       FXSYS_wcsftime(buf, std::size(buf), L"%y-%m-%dT%H:%M:%S", &bad_time));
321 
322   // Ensure wcsftime handles bad-ish day without crashing (Feb 30).
323   struct tm feb_time = {};
324   feb_time.tm_year = 115;  // 1900-based.
325   feb_time.tm_mon = 1;     // 0-based.
326   feb_time.tm_mday = 30;   // 1-based.
327   feb_time.tm_hour = 12;
328   feb_time.tm_min = 00;
329   feb_time.tm_sec = 00;
330 
331   UNSAFE_TODO(
332       FXSYS_wcsftime(buf, std::size(buf), L"%y-%m-%dT%H:%M:%S", &feb_time));
333 }
334 
TEST(fxcrt,FXSYSatoi)335 TEST(fxcrt, FXSYSatoi) {
336   EXPECT_EQ(0, FXSYS_atoi(""));
337   EXPECT_EQ(0, FXSYS_atoi("0"));
338   EXPECT_EQ(-1, FXSYS_atoi("-1"));
339   EXPECT_EQ(2345, FXSYS_atoi("2345"));
340   EXPECT_EQ(-2147483647, FXSYS_atoi("-2147483647"));
341   // Handle the sign.
342   EXPECT_EQ(-2345, FXSYS_atoi("-2345"));
343   EXPECT_EQ(2345, FXSYS_atoi("+2345"));
344   // The max value.
345   EXPECT_EQ(2147483647, FXSYS_atoi("2147483647"));
346   // The min value. Written in -1 format to avoid "unary minus operator applied
347   // to unsigned type" warning.
348   EXPECT_EQ(-2147483647 - 1, FXSYS_atoi("-2147483648"));
349   // With invalid char.
350   EXPECT_EQ(9, FXSYS_atoi("9x9"));
351 
352   // Out of range values.
353   EXPECT_EQ(2147483647, FXSYS_atoi("2147483623423412348"));
354   EXPECT_EQ(2147483647, FXSYS_atoi("2147483648"));
355   EXPECT_EQ(-2147483647 - 1, FXSYS_atoi("-2147483650"));
356 }
357 
TEST(fxcrt,FXSYSatoi64)358 TEST(fxcrt, FXSYSatoi64) {
359   EXPECT_EQ(0, FXSYS_atoi64(""));
360   EXPECT_EQ(0, FXSYS_atoi64("0"));
361   EXPECT_EQ(-1, FXSYS_atoi64("-1"));
362   EXPECT_EQ(2345, FXSYS_atoi64("2345"));
363   EXPECT_EQ(-9223372036854775807LL, FXSYS_atoi64("-9223372036854775807"));
364   // Handle the sign.
365   EXPECT_EQ(-2345, FXSYS_atoi64("-2345"));
366   EXPECT_EQ(2345, FXSYS_atoi64("+2345"));
367   // The max value.
368   EXPECT_EQ(9223372036854775807LL, FXSYS_atoi64("9223372036854775807"));
369   // The min value. Written in -1 format to avoid implicit unsigned warning.
370   EXPECT_EQ(-9223372036854775807LL - 1LL, FXSYS_atoi64("-9223372036854775808"));
371   // With invalid char.
372   EXPECT_EQ(9, FXSYS_atoi64("9x9"));
373 
374   // Out of range values.
375   EXPECT_EQ(9223372036854775807LL, FXSYS_atoi64("922337203685471234123475807"));
376   EXPECT_EQ(9223372036854775807LL, FXSYS_atoi64("9223372036854775808"));
377   EXPECT_EQ(-9223372036854775807LL - 1LL, FXSYS_atoi64("-9223372036854775810"));
378 }
379 
TEST(fxcrt,FXSYSwtoi)380 TEST(fxcrt, FXSYSwtoi) {
381   EXPECT_EQ(0, FXSYS_wtoi(L""));
382   EXPECT_EQ(0, FXSYS_wtoi(L"0"));
383   EXPECT_EQ(-1, FXSYS_wtoi(L"-1"));
384   EXPECT_EQ(2345, FXSYS_wtoi(L"2345"));
385   EXPECT_EQ(-2147483647, FXSYS_wtoi(L"-2147483647"));
386   // The max value.
387   EXPECT_EQ(2147483647, FXSYS_wtoi(L"2147483647"));
388   // The min value.
389   EXPECT_EQ(-2147483647 - 1, FXSYS_wtoi(L"-2147483648"));
390 
391   // Out of range values.
392   EXPECT_EQ(2147483647, FXSYS_wtoi(L"2147483623423412348"));
393   EXPECT_EQ(2147483647, FXSYS_wtoi(L"2147483648"));
394   EXPECT_EQ(-2147483647 - 1, FXSYS_wtoi(L"-2147483652"));
395 }
396 
TEST(fxcrt,FXSYSatoui)397 TEST(fxcrt, FXSYSatoui) {
398   EXPECT_EQ(0u, FXSYS_atoui(""));
399   EXPECT_EQ(0u, FXSYS_atoui("0"));
400   EXPECT_EQ(4294967295, FXSYS_atoui("-1"));
401   EXPECT_EQ(2345u, FXSYS_atoui("2345"));
402   // Handle the sign.
403   EXPECT_EQ(4294964951, FXSYS_atoui("-2345"));
404   EXPECT_EQ(2345u, FXSYS_atoui("+2345"));
405   // The max value.
406   EXPECT_EQ(4294967295, FXSYS_atoui("4294967295"));
407   EXPECT_EQ(9u, FXSYS_atoui("9x9"));
408 
409   // Out of range values.
410   EXPECT_EQ(4294967295, FXSYS_atoui("2147483623423412348"));
411   EXPECT_EQ(4294967295, FXSYS_atoui("4294967296"));
412   EXPECT_EQ(4294967295, FXSYS_atoui("-4294967345"));
413 }
414