(trunk libT) #2046: fix JSON bug when parsing floating point numbers in some locales

This commit is contained in:
Charles Kerr 2009-05-09 18:01:29 +00:00
parent a0e34bc270
commit 7f08a87969
2 changed files with 13 additions and 9 deletions

View File

@ -54,6 +54,7 @@ SOFTWARE.
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <float.h> #include <float.h>
#include <locale.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -476,7 +477,13 @@ static int parse_parse_buffer(JSON_parser jc)
value.vu.str.value = jc->parse_buffer; value.vu.str.value = jc->parse_buffer;
value.vu.str.length = jc->parse_buffer_count; value.vu.str.length = jc->parse_buffer_count;
} else { } else {
/* the json spec requires a '.' decimal point regardless of locale */
char numeric[128];
snprintf(numeric, sizeof(numeric), "%s", setlocale(LC_NUMERIC, NULL));
setlocale(LC_NUMERIC, "POSIX" );
sscanf(jc->parse_buffer, "%Lf", &value.vu.float_value); sscanf(jc->parse_buffer, "%Lf", &value.vu.float_value);
value.vu.float_value = strtod(jc->parse_buffer, NULL);
setlocale(LC_NUMERIC, numeric);
} }
break; break;
case JSON_T_INTEGER: case JSON_T_INTEGER:

View File

@ -479,15 +479,14 @@ tr_bencGetReal( const tr_benc * val, double * setme )
if( !success && tr_bencIsString(val) ) if( !success && tr_bencIsString(val) )
{ {
char * endptr; char * endptr;
char * locale; char locale[128];
double d; double d;
/* the json spec requires a '.' decimal point regardless of locale */ /* the json spec requires a '.' decimal point regardless of locale */
locale = tr_strdup( setlocale ( LC_NUMERIC, NULL ) ); tr_strlcpy( locale, setlocale( LC_NUMERIC, NULL ), sizeof( locale ) );
setlocale( LC_NUMERIC, "POSIX" ); setlocale( LC_NUMERIC, "POSIX" );
d = strtod( val->val.s.s, &endptr ); d = strtod( val->val.s.s, &endptr );
setlocale( LC_NUMERIC, locale ); setlocale( LC_NUMERIC, locale );
tr_free( locale );
if(( success = ( val->val.s.s != endptr ) && !*endptr )) if(( success = ( val->val.s.s != endptr ) && !*endptr ))
*setme = d; *setme = d;
@ -1062,15 +1061,14 @@ static void
saveRealFunc( const tr_benc * val, void * evbuf ) saveRealFunc( const tr_benc * val, void * evbuf )
{ {
char buf[128]; char buf[128];
char * locale; char locale[128];
size_t len; size_t len;
/* always use a '.' decimal point s.t. locale-hopping doesn't bite us */ /* always use a '.' decimal point s.t. locale-hopping doesn't bite us */
locale = tr_strdup( setlocale ( LC_NUMERIC, NULL ) ); tr_strlcpy( locale, setlocale( LC_NUMERIC, NULL ), sizeof( locale ) );
setlocale( LC_NUMERIC, "POSIX" ); setlocale( LC_NUMERIC, "POSIX" );
tr_snprintf( buf, sizeof( buf ), "%f", val->val.d ); tr_snprintf( buf, sizeof( buf ), "%f", val->val.d );
setlocale( LC_NUMERIC, locale ); setlocale( LC_NUMERIC, locale );
tr_free( locale );
len = strlen( buf ); len = strlen( buf );
evbuffer_add_printf( evbuf, "%lu:", (unsigned long)len ); evbuffer_add_printf( evbuf, "%lu:", (unsigned long)len );
@ -1278,14 +1276,13 @@ static void
jsonRealFunc( const tr_benc * val, void * vdata ) jsonRealFunc( const tr_benc * val, void * vdata )
{ {
struct jsonWalk * data = vdata; struct jsonWalk * data = vdata;
char * locale; char locale[128];
/* json requires a '.' decimal point regardless of locale */ /* json requires a '.' decimal point regardless of locale */
locale = tr_strdup( setlocale ( LC_NUMERIC, NULL ) ); tr_strlcpy( locale, setlocale( LC_NUMERIC, NULL ), sizeof( locale ) );
setlocale( LC_NUMERIC, "POSIX" ); setlocale( LC_NUMERIC, "POSIX" );
evbuffer_add_printf( data->out, "%f", val->val.d ); evbuffer_add_printf( data->out, "%f", val->val.d );
setlocale( LC_NUMERIC, locale ); setlocale( LC_NUMERIC, locale );
tr_free( locale );
jsonChildFunc( data ); jsonChildFunc( data );
} }