@@ -414,7 +414,29 @@ fossil_media_fson_value_t *fossil_media_fson_parse(const char *json_text, fossil
414414 memcpy (dt_str , dt_start , dt_len );
415415 }
416416 dt_str [dt_len ] = '\0' ;
417- val = fossil_media_fson_new_datetime (dt_str );
417+
418+ // Basic validation: must contain at least one digit and a separator
419+ int valid = 0 ;
420+ for (size_t i = 0 ; i < dt_len ; i ++ ) {
421+ if (isdigit ((unsigned char )dt_str [i ])) {
422+ valid = 1 ;
423+ break ;
424+ }
425+ }
426+ if (valid && strchr (dt_str , '-' ) != NULL ) {
427+ val = fossil_media_fson_new_datetime (dt_str );
428+ } else {
429+ free (dt_str );
430+ free (key );
431+ free (type );
432+ fossil_media_fson_free (obj );
433+ if (err_out ) {
434+ err_out -> code = FOSSIL_MEDIA_FSON_ERR_TYPE ;
435+ err_out -> position = (size_t )(json_text - input_start );
436+ snprintf (err_out -> message , sizeof (err_out -> message ), "Invalid datetime format" );
437+ }
438+ return NULL ;
439+ }
418440 free (dt_str );
419441 if (* json_text == '"' ) json_text ++ ;
420442 }
@@ -442,7 +464,30 @@ fossil_media_fson_value_t *fossil_media_fson_parse(const char *json_text, fossil
442464 memcpy (dur_str , dur_start , dur_len );
443465 }
444466 dur_str [dur_len ] = '\0' ;
445- val = fossil_media_fson_new_duration (dur_str );
467+ // Basic validation: must contain at least one digit or time unit (e.g., 's', 'm', 'h')
468+ int valid = 0 ;
469+ for (size_t i = 0 ; i < dur_len ; i ++ ) {
470+ if (isdigit ((unsigned char )dur_str [i ]) ||
471+ dur_str [i ] == 's' || dur_str [i ] == 'm' || dur_str [i ] == 'h' ||
472+ dur_str [i ] == 'd' ) {
473+ valid = 1 ;
474+ break ;
475+ }
476+ }
477+ if (valid ) {
478+ val = fossil_media_fson_new_duration (dur_str );
479+ } else {
480+ free (dur_str );
481+ free (key );
482+ free (type );
483+ fossil_media_fson_free (obj );
484+ if (err_out ) {
485+ err_out -> code = FOSSIL_MEDIA_FSON_ERR_TYPE ;
486+ err_out -> position = (size_t )(json_text - input_start );
487+ snprintf (err_out -> message , sizeof (err_out -> message ), "Invalid duration format" );
488+ }
489+ return NULL ;
490+ }
446491 free (dur_str );
447492 if (* json_text == '"' ) json_text ++ ;
448493 }
@@ -2006,7 +2051,21 @@ int fossil_media_fson_equals(const fossil_media_fson_value_t *a, const fossil_me
20062051 }
20072052 return (strcmp (a -> u .enum_val .symbol , b -> u .enum_val .symbol ) == 0 ) ? 1 : 0 ;
20082053 case FSON_TYPE_DATETIME :
2054+ if (a -> u .cstr == NULL && b -> u .cstr == NULL ) {
2055+ return 1 ;
2056+ }
2057+ if (a -> u .cstr == NULL || b -> u .cstr == NULL ) {
2058+ return 0 ;
2059+ }
2060+ return (strcmp (a -> u .cstr , b -> u .cstr ) == 0 ) ? 1 : 0 ;
20092061 case FSON_TYPE_DURATION :
2062+ if (a -> u .cstr == NULL && b -> u .cstr == NULL ) {
2063+ return 1 ;
2064+ }
2065+ if (a -> u .cstr == NULL || b -> u .cstr == NULL ) {
2066+ return 0 ;
2067+ }
2068+ return (strcmp (a -> u .cstr , b -> u .cstr ) == 0 ) ? 1 : 0 ;
20102069 case FSON_TYPE_ARRAY :
20112070 if (a -> u .array .count != b -> u .array .count ) {
20122071 return 0 ;
0 commit comments