OLD | NEW |
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 /* This Source Code Form is subject to the terms of the Mozilla Public | 2 /* This Source Code Form is subject to the terms of the Mozilla Public |
3 * License, v. 2.0. If a copy of the MPL was not distributed with this | 3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | 5 |
6 /* | 6 /* |
7 ** Portable safe sprintf code. | 7 ** Portable safe sprintf code. |
8 ** | 8 ** |
9 ** Author: Kipp E.B. Hickman | 9 ** Author: Kipp E.B. Hickman |
10 */ | 10 */ |
11 #include <stdarg.h> | 11 #include <stdarg.h> |
12 #include <stddef.h> | 12 #include <stddef.h> |
13 #include <stdio.h> | 13 #include <stdio.h> |
14 #include <string.h> | 14 #include <string.h> |
15 #include "primpl.h" | 15 #include "primpl.h" |
16 #include "prprf.h" | 16 #include "prprf.h" |
17 #include "prlong.h" | 17 #include "prlong.h" |
18 #include "prlog.h" | 18 #include "prlog.h" |
19 #include "prmem.h" | 19 #include "prmem.h" |
20 | 20 |
| 21 #ifdef _MSC_VER |
| 22 #define snprintf _snprintf |
| 23 #endif |
| 24 |
21 /* | 25 /* |
22 ** WARNING: This code may *NOT* call PR_LOG (because PR_LOG calls it) | 26 ** WARNING: This code may *NOT* call PR_LOG (because PR_LOG calls it) |
23 */ | 27 */ |
24 | 28 |
25 /* | 29 /* |
26 ** XXX This needs to be internationalized! | 30 ** XXX This needs to be internationalized! |
27 */ | 31 */ |
28 | 32 |
29 typedef struct SprintfStateStr SprintfState; | 33 typedef struct SprintfStateStr SprintfState; |
30 | 34 |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 ** Now that we have the number converted without its sign, deal with | 301 ** Now that we have the number converted without its sign, deal with |
298 ** the sign and zero padding. | 302 ** the sign and zero padding. |
299 */ | 303 */ |
300 return fill_n(ss, cvt, digits, width, prec, type, flags); | 304 return fill_n(ss, cvt, digits, width, prec, type, flags); |
301 } | 305 } |
302 | 306 |
303 /* | 307 /* |
304 ** Convert a double precision floating point number into its printable | 308 ** Convert a double precision floating point number into its printable |
305 ** form. | 309 ** form. |
306 ** | 310 ** |
307 ** XXX stop using sprintf to convert floating point | 311 ** XXX stop using snprintf to convert floating point |
308 */ | 312 */ |
309 static int cvt_f(SprintfState *ss, double d, const char *fmt0, const char *fmt1) | 313 static int cvt_f(SprintfState *ss, double d, const char *fmt0, const char *fmt1) |
310 { | 314 { |
311 char fin[20]; | 315 char fin[20]; |
312 char fout[300]; | 316 char fout[300]; |
313 int amount = fmt1 - fmt0; | 317 int amount = fmt1 - fmt0; |
314 | 318 |
315 PR_ASSERT((amount > 0) && (amount < sizeof(fin))); | 319 if (amount <= 0 || amount >= sizeof(fin)) { |
316 if (amount >= sizeof(fin)) { | 320 » /* Totally bogus % command to snprintf. Just ignore it */ |
317 » /* Totally bogus % command to sprintf. Just ignore it */ | |
318 return 0; | 321 return 0; |
319 } | 322 } |
320 memcpy(fin, fmt0, amount); | 323 memcpy(fin, fmt0, amount); |
321 fin[amount] = 0; | 324 fin[amount] = 0; |
322 | 325 |
323 /* Convert floating point using the native sprintf code */ | 326 /* Convert floating point using the native snprintf code */ |
324 #ifdef DEBUG | 327 #ifdef DEBUG |
325 { | 328 { |
326 const char *p = fin; | 329 const char *p = fin; |
327 while (*p) { | 330 while (*p) { |
328 PR_ASSERT(*p != 'L'); | 331 PR_ASSERT(*p != 'L'); |
329 p++; | 332 p++; |
330 } | 333 } |
331 } | 334 } |
332 #endif | 335 #endif |
333 sprintf(fout, fin, d); | 336 memset(fout, 0, sizeof(fout)); |
334 | 337 snprintf(fout, sizeof(fout), fin, d); |
335 /* | 338 /* Explicitly null-terminate fout because on Windows snprintf doesn't |
336 ** This assert will catch overflow's of fout, when building with | 339 * append a null-terminator if the buffer is too small. */ |
337 ** debugging on. At least this way we can track down the evil piece | 340 fout[sizeof(fout) - 1] = '\0'; |
338 ** of calling code and fix it! | |
339 */ | |
340 PR_ASSERT(strlen(fout) < sizeof(fout)); | |
341 | 341 |
342 return (*ss->stuff)(ss, fout, strlen(fout)); | 342 return (*ss->stuff)(ss, fout, strlen(fout)); |
343 } | 343 } |
344 | 344 |
345 /* | 345 /* |
346 ** Convert a string into its printable form. "width" is the output | 346 ** Convert a string into its printable form. "width" is the output |
347 ** width. "prec" is the maximum number of characters of "s" to output, | 347 ** width. "prec" is the maximum number of characters of "s" to output, |
348 ** where -1 means until NUL. | 348 ** where -1 means until NUL. |
349 */ | 349 */ |
350 static int cvt_s(SprintfState *ss, const char *str, int width, int prec, | 350 static int cvt_s(SprintfState *ss, const char *str, int width, int prec, |
(...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1239 rv = dosprintf(&ss, fmt, ap); | 1239 rv = dosprintf(&ss, fmt, ap); |
1240 if (rv < 0) { | 1240 if (rv < 0) { |
1241 if (ss.base) { | 1241 if (ss.base) { |
1242 PR_DELETE(ss.base); | 1242 PR_DELETE(ss.base); |
1243 } | 1243 } |
1244 return 0; | 1244 return 0; |
1245 } | 1245 } |
1246 return ss.base; | 1246 return ss.base; |
1247 } | 1247 } |
1248 | 1248 |
OLD | NEW |