@@ -382,7 +382,7 @@ static bool check_char(JNIEnv* env, const jchar *s, int spos, jchar expected)
382382 jchar c = s[spos];
383383 if (c != expected) {
384384 char msg[100 ];
385- sprintf (msg, " Unexpected %c at pos=%d. Expected %c." , c, spos,
385+ sprintf (msg, " Unexpected character 0x%02x at pos=%d. Expected %c." , c, spos,
386386 expected);
387387 jniThrowException (env, " android/util/TimeFormatException" , msg);
388388 return false ;
@@ -483,6 +483,12 @@ static jboolean android_text_format_Time_parse3339(JNIEnv* env,
483483 int n;
484484 jboolean inUtc = false ;
485485
486+ if (len < 10 ) {
487+ jniThrowException (env, " android/util/TimeFormatException" ,
488+ " Time input is too short; must be at least 10 characters" );
489+ return false ;
490+ }
491+
486492 // year
487493 n = get_char (env, s, 0 , 1000 , &thrown);
488494 n += get_char (env, s, 1 , 100 , &thrown);
@@ -510,7 +516,7 @@ static jboolean android_text_format_Time_parse3339(JNIEnv* env,
510516 if (thrown) return false ;
511517 env->SetIntField (This, g_mdayField, n);
512518
513- if (len >= 17 ) {
519+ if (len >= 19 ) {
514520 // T
515521 if (!check_char (env, s, 10 , ' T' )) return false ;
516522
@@ -541,10 +547,19 @@ static jboolean android_text_format_Time_parse3339(JNIEnv* env,
541547 if (thrown) return false ;
542548 env->SetIntField (This, g_secField, n);
543549
544- // skip the '.XYZ' -- we don't care about subsecond precision.
550+ // skip the '.XYZ' -- we don't care about subsecond precision.
551+ int tz_index = 19 ;
552+ if (tz_index < len && s[tz_index] == ' .' ) {
553+ do {
554+ tz_index++;
555+ } while (tz_index < len
556+ && s[tz_index] >= ' 0'
557+ && s[tz_index] <= ' 9' );
558+ }
559+
545560 int offset = 0 ;
546- if (len >= 23 ) {
547- char c = s[23 ];
561+ if (len > tz_index ) {
562+ char c = s[tz_index ];
548563
549564 // NOTE: the offset is meant to be subtracted to get from local time
550565 // to UTC. we therefore use 1 for '-' and -1 for '+'.
@@ -561,27 +576,34 @@ static jboolean android_text_format_Time_parse3339(JNIEnv* env,
561576 break ;
562577 default :
563578 char msg[100 ];
564- sprintf (msg, " Unexpected %c at position 19 . Expected + or -" ,
565- c);
579+ sprintf (msg, " Unexpected character 0x%02x at position %d . Expected + or -" ,
580+ c, tz_index );
566581 jniThrowException (env, " android/util/TimeFormatException" , msg);
567582 return false ;
568583 }
569584 inUtc = true ;
570585
571586 if (offset != 0 ) {
587+ if (len < tz_index + 5 ) {
588+ char msg[100 ];
589+ sprintf (msg, " Unexpected length; should be %d characters" , tz_index + 5 );
590+ jniThrowException (env, " android/util/TimeFormatException" , msg);
591+ return false ;
592+ }
593+
572594 // hour
573- n = get_char (env, s, 24 , 10 , &thrown);
574- n += get_char (env, s, 25 , 1 , &thrown);
595+ n = get_char (env, s, tz_index + 1 , 10 , &thrown);
596+ n += get_char (env, s, tz_index + 2 , 1 , &thrown);
575597 if (thrown) return false ;
576598 n *= offset;
577599 hour += n;
578600
579601 // :
580- if (!check_char (env, s, 26 , ' :' )) return false ;
602+ if (!check_char (env, s, tz_index + 3 , ' :' )) return false ;
581603
582604 // minute
583- n = get_char (env, s, 27 , 10 , &thrown);
584- n += get_char (env, s, 28 , 1 , &thrown);
605+ n = get_char (env, s, tz_index + 4 , 10 , &thrown);
606+ n += get_char (env, s, tz_index + 5 , 1 , &thrown);
585607 if (thrown) return false ;
586608 n *= offset;
587609 minute += n;
0 commit comments