From 54c69d2380587f1db026b0773cae1430da42e184 Mon Sep 17 00:00:00 2001 From: Eugen Sawin Date: Sun, 21 Jul 2019 17:36:41 +0000 Subject: [PATCH] Bug 1501108 - [5.1] Ensure that the context ID string is safe for Gecko processing. r=Ehsan,geckoview-reviewers,agi Differential Revision: https://phabricator.services.mozilla.com/D38188 --HG-- extra : moz-landing-system : lando --- .../geckoview/GeckoSessionSettings.java | 16 ++++++++++++--- .../mozilla/geckoview/StorageController.java | 20 ++++++++++++++++++- .../modules/geckoview/GeckoViewNavigation.jsm | 5 +++++ 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java index 5a656d8d92ee..cea23c46945e 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java @@ -336,11 +336,18 @@ public final class GeckoSessionSettings implements Parcelable { new Key("fullAccessibilityTree", /* initOnly */ false, /* values */ null); /** - * Key to specify the session context ID. + * Internal Gecko key to specify the session context ID. + * Derived from `UNSAFE_CONTEXT_ID`. */ private static final Key CONTEXT_ID = new Key("sessionContextId", /* initOnly */ true, /* values */ null); + /** + * User-provided key to specify the session context ID. + */ + private static final Key UNSAFE_CONTEXT_ID = + new Key("unsafeSessionContextId", /* initOnly */ true, /* values */ null); + private final GeckoSession mSession; private final GeckoBundle mBundle; @@ -375,6 +382,7 @@ public final class GeckoSessionSettings implements Parcelable { mBundle.putInt(VIEWPORT_MODE.name, VIEWPORT_MODE_MOBILE); mBundle.putInt(DISPLAY_MODE.name, DISPLAY_MODE_BROWSER); mBundle.putString(CONTEXT_ID.name, null); + mBundle.putString(UNSAFE_CONTEXT_ID.name, null); } /** @@ -473,7 +481,8 @@ public final class GeckoSessionSettings implements Parcelable { * @return The context ID for this session. */ public @Nullable String getContextId() { - return getString(CONTEXT_ID); + // Return the user-provided unsafe string. + return getString(UNSAFE_CONTEXT_ID); } /** @@ -635,7 +644,8 @@ public final class GeckoSessionSettings implements Parcelable { } private void setContextId(final @Nullable String value) { - setString(CONTEXT_ID, value); + setString(UNSAFE_CONTEXT_ID, value); + setString(CONTEXT_ID, StorageController.createSafeSessionContextId(value)); } private void setString(final Key key, final String value) { diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/StorageController.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/StorageController.java index 630f99f6bc5b..f930a796afda 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/StorageController.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/StorageController.java @@ -8,10 +8,12 @@ package org.mozilla.geckoview; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.math.BigInteger; import android.support.annotation.AnyThread; import android.support.annotation.LongDef; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import org.mozilla.gecko.EventDispatcher; import org.mozilla.gecko.util.GeckoBundle; @@ -175,9 +177,25 @@ public final class StorageController { @AnyThread public void clearDataForSessionContext(final @NonNull String contextId) { final GeckoBundle bundle = new GeckoBundle(1); - bundle.putString("contextId", contextId); + bundle.putString("contextId", createSafeSessionContextId(contextId)); EventDispatcher.getInstance().dispatch( "GeckoView:ClearSessionContextData", bundle); } + + /* package */ static @NonNull String createSafeSessionContextId( + final @Nullable String contextId) { + if (contextId == null) { + return null; + } + if (contextId.isEmpty()) { + // Let's avoid empty strings for Gecko. + return "gvctxempty"; + } + // We don't want to restrict the session context ID string options, so to + // ensure that the string is safe for Gecko processing, we translate it to + // its hex representation. + return String.format("gvctx%x", new BigInteger(contextId.getBytes())) + .toLowerCase(); + } } diff --git a/mobile/android/modules/geckoview/GeckoViewNavigation.jsm b/mobile/android/modules/geckoview/GeckoViewNavigation.jsm index da3dc3a5456f..656bfa80086f 100644 --- a/mobile/android/modules/geckoview/GeckoViewNavigation.jsm +++ b/mobile/android/modules/geckoview/GeckoViewNavigation.jsm @@ -76,6 +76,11 @@ class GeckoViewNavigation extends GeckoViewModule { debug`sessionContextId=${this.settings.sessionContextId}`; if (this.settings.sessionContextId !== null) { + // Gecko may have issues with strings containing special characters, + // so we restrict the string format to a specific pattern. + if (!/^gvctx(-)?([a-f0-9]+)$/.test(this.settings.sessionContextId)) { + throw new Error("sessionContextId has illegal format"); + } this.browser.webNavigation.setOriginAttributesBeforeLoading({ geckoViewSessionContextId: this.settings.sessionContextId, privateBrowsingId: PrivateBrowsingUtils.isBrowserPrivate(this.browser)