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