Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5ef49427 authored by Elliott Hughes's avatar Elliott Hughes Committed by Raph Levien
Browse files

Fix Time.parse and Time.parse3339 crashing bugs. DO NOT MERGE

Two reported by users, the other spotted by inspection.

Bug: http://code.google.com/p/android/issues/detail?id=16002
Bug: http://code.google.com/p/android/issues/detail?id=22225
Change-Id: I86fe022fda4af68e5a6fb9dc5dd2abdb75e9d966

This was committed to master, cherry-picking to jb-mr1-dev
parent 37ee5342
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -437,6 +437,9 @@ public class Time {
     * @throws android.util.TimeFormatException if s cannot be parsed.
     */
    public boolean parse(String s) {
        if (s == null) {
            throw new NullPointerException("time string is null");
        }
        if (nativeParse(s)) {
            timezone = TIMEZONE_UTC;
            return true;
+93 −99
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "jni.h"
#include "utils/misc.h"
#include "android_runtime/AndroidRuntime.h"
#include "ScopedStringChars.h"
#include "TimeUtils.h"
#include <nativehelper/JNIHelp.h>
#include <cutils/tztime.h>
@@ -72,9 +73,8 @@ static inline bool java2time(JNIEnv* env, Time* t, jobject o)
    bool allDay = env->GetBooleanField(o, g_allDayField);
    if (allDay &&
       ((t->t.tm_sec !=0) || (t->t.tm_min != 0) || (t->t.tm_hour != 0))) {
        char msg[100];
	sprintf(msg, "allDay is true but sec, min, hour are not 0.");
	jniThrowException(env, "java/lang/IllegalArgumentException", msg);
        jniThrowException(env, "java/lang/IllegalArgumentException",
                          "allDay is true but sec, min, hour are not 0.");
        return false;
    }
    return true;
@@ -308,7 +308,7 @@ static jstring android_text_format_Time_format(JNIEnv* env, jobject This,
static jstring android_text_format_Time_toString(JNIEnv* env, jobject This)
{
    Time t;
    if (!java2time(env, &t, This)) return env->NewStringUTF("");;
    if (!java2time(env, &t, This)) return env->NewStringUTF("");
    ACQUIRE_TIMEZONE(This, t)

    String8 r = t.toString();
@@ -360,7 +360,7 @@ static void android_text_format_Time_set(JNIEnv* env, jobject This, jlong millis
// ============================================================================
// Just do this here because it's not worth recreating the strings

static int get_char(JNIEnv* env, const jchar *s, int spos, int mul,
static int get_char(JNIEnv* env, const ScopedStringChars& s, int spos, int mul,
                    bool* thrown)
{
    jchar c = s[spos];
@@ -368,23 +368,21 @@ static int get_char(JNIEnv* env, const jchar *s, int spos, int mul,
        return (c - '0') * mul;
    } else {
        if (!*thrown) {
            char msg[100];
            sprintf(msg, "Parse error at pos=%d", spos);
            jniThrowException(env, "android/util/TimeFormatException", msg);
            jniThrowExceptionFmt(env, "android/util/TimeFormatException",
                                 "Parse error at pos=%d", spos);
            *thrown = true;
        }
        return 0;
    }
}

static bool check_char(JNIEnv* env, const jchar *s, int spos, jchar expected)
static bool check_char(JNIEnv* env, const ScopedStringChars& s, int spos, jchar expected)
{
    jchar c = s[spos];
    if (c != expected) {
        char msg[100];
	sprintf(msg, "Unexpected character 0x%02x at pos=%d.  Expected %c.", c, spos,
		expected);
	jniThrowException(env, "android/util/TimeFormatException", msg);
        jniThrowExceptionFmt(env, "android/util/TimeFormatException",
                             "Unexpected character 0x%02x at pos=%d.  Expected %c.",
                             c, spos, expected);
        return false;
    }
    return true;
@@ -394,20 +392,19 @@ static bool check_char(JNIEnv* env, const jchar *s, int spos, jchar expected)
static jboolean android_text_format_Time_parse(JNIEnv* env, jobject This, jstring strObj)
{
    jsize len = env->GetStringLength(strObj);
    const jchar *s = env->GetStringChars(strObj, NULL);

    bool thrown = false;
    int n;
    jboolean inUtc = false;

    if (len < 8) {
        char msg[100];
        sprintf(msg, "String too short -- expected at least 8 characters.");
	jniThrowException(env, "android/util/TimeFormatException", msg);
        jniThrowException(env, "android/util/TimeFormatException",
                          "String too short -- expected at least 8 characters.");
        return false;
    }

    jboolean inUtc = false;

    ScopedStringChars s(env, strObj);

    // year
    int n;
    bool thrown = false;
    n = get_char(env, s, 0, 1000, &thrown);
    n += get_char(env, s, 1, 100, &thrown);
    n += get_char(env, s, 2, 10, &thrown);
@@ -468,7 +465,6 @@ static jboolean android_text_format_Time_parse(JNIEnv* env, jobject This, jstrin
    env->SetIntField(This, g_isdstField, -1);
    env->SetLongField(This, g_gmtoffField, 0);

    env->ReleaseStringChars(strObj, s);
    return inUtc;
}

@@ -477,19 +473,19 @@ static jboolean android_text_format_Time_parse3339(JNIEnv* env,
                                           jstring strObj)
{
    jsize len = env->GetStringLength(strObj);
    const jchar *s = env->GetStringChars(strObj, NULL);

    bool thrown = false;
    int n;
    jboolean inUtc = false;

    if (len < 10) {
        jniThrowException(env, "android/util/TimeFormatException",
                "Time input is too short; must be at least 10 characters");
                          "String too short --- expected at least 10 characters.");
        return false;
    }

    jboolean inUtc = false;

    ScopedStringChars s(env, strObj);

    // year
    int n;
    bool thrown = false;
    n = get_char(env, s, 0, 1000, &thrown);    
    n += get_char(env, s, 1, 100, &thrown);
    n += get_char(env, s, 2, 10, &thrown);
@@ -575,19 +571,18 @@ static jboolean android_text_format_Time_parse3339(JNIEnv* env,
                offset = -1;
                break;
            default:
	        char msg[100];
	        sprintf(msg, "Unexpected character 0x%02x at position %d.  Expected + or -",
                jniThrowExceptionFmt(env, "android/util/TimeFormatException",
                                     "Unexpected character 0x%02x at position %d.  Expected + or -",
                                     c, tz_index);
	        jniThrowException(env, "android/util/TimeFormatException", msg);
                return false;
            }
            inUtc = true;

            if (offset != 0) {
                if (len < tz_index + 6) {
	            char msg[100];
	            sprintf(msg, "Unexpected length; should be %d characters", tz_index + 6);
	            jniThrowException(env, "android/util/TimeFormatException", msg);
                    jniThrowExceptionFmt(env, "android/util/TimeFormatException",
                                         "Unexpected length; should be %d characters",
                                         tz_index + 6);
                    return false;
                }

@@ -629,7 +624,6 @@ static jboolean android_text_format_Time_parse3339(JNIEnv* env,
    env->SetIntField(This, g_isdstField, -1);
    env->SetLongField(This, g_gmtoffField, 0);

    env->ReleaseStringChars(strObj, s);
    return inUtc;
}