View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000528 | LDMud 3.3 | Portability | public | 2008-01-27 16:04 | 2018-01-29 21:57 |
Reporter | zesstra | Assigned To | zesstra | ||
Priority | normal | Severity | minor | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Platform | x86_64 | OS | MacOS X | OS Version | 10.5.x |
Product Version | 3.3 | ||||
Fixed in Version | 3.3.718 | ||||
Summary | 0000528: sprintf() fails to print int values larger than 2^32 - 1 correctly | ||||
Description | sprintf() assumes that LPC ints (T_NUMBER) are 32-bit ints and wraps at 2^31 to negative values and then again after 2^32 and so on and therefore truncates all values to the range of -2147483647 and 2147483647. | ||||
Steps To Reproduce | printf("%d\n", __INT_MAX__) on 64-bit platforms. | ||||
Tags | No tags attached. | ||||
Attached Files | sprintf_64bit-V2.diff (1,957 bytes)
Index: src/sprintf.c =================================================================== --- src/sprintf.c (Revision 2364) +++ src/sprintf.c (Arbeitskopie) @@ -455,7 +455,7 @@ /*-------------------------------------------------------------------------*/ static void -numadd (fmt_state_t *st, sprintf_buffer_t **buffer, int num) +numadd (fmt_state_t *st, sprintf_buffer_t **buffer, p_int num) /* Add the <num>ber to the <buffer>. */ @@ -2243,7 +2243,7 @@ } else { - char cheat[6]; /* Synthesized format for sprintf() */ + char cheat[8]; /* Synthesized format for sprintf() */ char temp[1024]; /* The buffer must be big enough to hold the biggest float * in non-exponential representation. 1 KByte is hopefully @@ -2305,12 +2305,22 @@ * strings can. So in that case we format with * character 0x01 and convert to 0 afterwards. */ - if (format_char == 'c' && carg->u.number == 0) - { + if (format_char == 'c') { + if (carg->u.number == 0) + { carg->u.number = 1; zeroCharHack = MY_TRUE; + } } - + else + { +#if SIZEOF_LONG == SIZEOF_CHAR_P + cheat[i++] = 'l'; +#elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == SIZEOF_CHAR_P + cheat[i++] = 'l'; + cheat[i++] = 'l'; +#endif + } cheat[i++] = format_char; cheat[i] = '\0'; sprintf(temp, cheat, carg->u.number); | ||||
|
sprintf.c uses for T_FLOAT und T_NUMBER in most cases the system sprintf. Unfortunately, that needs a length modifier for long int ('l') and long long int ('ll'). I added some precompiler logic in string_print_formatted() around line 2314 to add 'l' or 'll' depending on the size of p_int (u.number in svalue). That works, but has to 2 issues: First it introduces stuff from port.h to sprintf.c, it would be nicer to keep that portability defines in port.h. Though I not sure, if it is practicable. Second and more important, the format_char can be 'c' as well and '%lc' signifies a wide char wint_t. It would be needed to change that part of string_print_formatted() to use the 'l' and 'll' length mods only for integral conversions (d, i, o, u, x, or X). I still have to do that and it is sadly an additional runtime decision. |
|
sprintf_64bit-V2.diff should fix the 2 obvious issues with sprintf() concerning 64-bit Ints and %d, %i, %x and %O. 1) change num_add(..., int num) to num_add(..., p_int num) 2) add 'l' or 'll' to %d, %i, %x (but not %c) before passing them on to the system lib. There are still a lot of warnings "implicit conversion shortens 64-bit value into a 32-bit value" in sprintf.c left and some of them might well be a bug. But they have to wait for another patch. |
|
Fixed in r2413. |
Date Modified | Username | Field | Change |
---|---|---|---|
2008-01-27 16:04 | zesstra | New Issue | |
2008-04-01 08:20 | zesstra | File Added: sprintf_64bit.diff | |
2008-05-02 14:44 | zesstra | Note Added: 0000610 | |
2008-05-02 15:38 | zesstra | File Added: sprintf_64bit-V2.diff | |
2008-05-06 13:32 | zesstra | Note Added: 0000613 | |
2008-06-30 02:55 | zesstra | Status | new => assigned |
2008-06-30 02:55 | zesstra | Assigned To | => zesstra |
2008-07-08 15:25 | zesstra | File Deleted: sprintf_64bit.diff | |
2008-07-12 16:17 | zesstra | Relationship added | parent of 0000554 |
2008-07-13 12:02 | zesstra | Relationship added | child of 0000555 |
2008-07-14 14:17 | zesstra | Relationship added | related to 0000556 |
2008-09-06 16:19 | zesstra | Status | assigned => resolved |
2008-09-06 16:19 | zesstra | Fixed in Version | => 3.3.718 |
2008-09-06 16:19 | zesstra | Resolution | open => fixed |
2008-09-06 16:19 | zesstra | Note Added: 0000762 | |
2010-11-16 09:42 | zesstra | Source_changeset_attached | => ldmud.git master d15b8b12 |
2018-01-29 18:59 | zesstra | Source_changeset_attached | => ldmud.git master d15b8b12 |
2018-01-29 21:57 | zesstra | Source_changeset_attached | => ldmud.git master d15b8b12 |