diff options
author | wolfbeast <mcwerewolf@gmail.com> | 2018-11-02 10:32:53 +0100 |
---|---|---|
committer | wolfbeast <mcwerewolf@gmail.com> | 2018-11-02 10:32:53 +0100 |
commit | deba73b3bc9168838034c2b5bab4b7d2945bfaaf (patch) | |
tree | b83278806048b9baf39c4d088ee87049116de1bd | |
parent | 09fec033ec18a5c0eb29815924114016cee32a00 (diff) | |
download | UXP-deba73b3bc9168838034c2b5bab4b7d2945bfaaf.tar UXP-deba73b3bc9168838034c2b5bab4b7d2945bfaaf.tar.gz UXP-deba73b3bc9168838034c2b5bab4b7d2945bfaaf.tar.lz UXP-deba73b3bc9168838034c2b5bab4b7d2945bfaaf.tar.xz UXP-deba73b3bc9168838034c2b5bab4b7d2945bfaaf.zip |
Fix a longstanding IndexedDB correctness issue.
Standards Compliance fix, port of Bug 1492737
-rw-r--r-- | dom/indexedDB/KeyPath.cpp | 77 | ||||
-rw-r--r-- | dom/xbl/nsXBLBinding.cpp | 3 | ||||
-rw-r--r-- | dom/xbl/nsXBLProtoImpl.cpp | 12 | ||||
-rw-r--r-- | js/src/jsapi.cpp | 18 | ||||
-rw-r--r-- | js/src/jsapi.h | 6 |
5 files changed, 99 insertions, 17 deletions
diff --git a/dom/indexedDB/KeyPath.cpp b/dom/indexedDB/KeyPath.cpp index dc8d10668..30edd8cd7 100644 --- a/dom/indexedDB/KeyPath.cpp +++ b/dom/indexedDB/KeyPath.cpp @@ -14,6 +14,7 @@ #include "xpcpublic.h" #include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/BlobBinding.h" #include "mozilla/dom/IDBObjectStoreBinding.h" namespace mozilla { @@ -100,7 +101,6 @@ GetJSValFromKeyPathString(JSContext* aCx, const char16_t* keyPathChars = token.BeginReading(); const size_t keyPathLen = token.Length(); - bool hasProp; if (!targetObject) { // We're still walking the chain of existing objects // http://w3c.github.io/IndexedDB/#dfn-evaluate-a-key-path-on-a-value @@ -116,16 +116,77 @@ GetJSValFromKeyPathString(JSContext* aCx, } obj = ¤tVal.toObject(); - bool ok = JS_HasUCProperty(aCx, obj, keyPathChars, keyPathLen, - &hasProp); + // We call JS_GetOwnUCPropertyDescriptor on purpose (as opposed to + // JS_GetUCPropertyDescriptor) to avoid searching the prototype chain. + JS::Rooted<JS::PropertyDescriptor> desc(aCx); + bool ok = JS_GetOwnUCPropertyDescriptor(aCx, obj, keyPathChars, + keyPathLen, &desc); IDB_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - if (hasProp) { - // Get if the property exists... - JS::Rooted<JS::Value> intermediate(aCx); - bool ok = JS_GetUCProperty(aCx, obj, keyPathChars, keyPathLen, &intermediate); - IDB_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + JS::Rooted<JS::Value> intermediate(aCx); + bool hasProp = false; + + if (desc.object()) { + intermediate = desc.value(); + hasProp = true; + } else { + // If we get here it means the object doesn't have the property or the + // property is available throuch a getter. We don't want to call any + // getters to avoid potential re-entrancy. + // The blob object is special since its properties are available + // only through getters but we still want to support them for key + // extraction. So they need to be handled manually. + Blob* blob; + if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, &obj, blob))) { + if (token.EqualsLiteral("size")) { + ErrorResult rv; + uint64_t size = blob->GetSize(rv); + MOZ_ALWAYS_TRUE(!rv.Failed()); + + intermediate = JS_NumberValue(size); + hasProp = true; + } else if (token.EqualsLiteral("type")) { + nsString type; + blob->GetType(type); + + JSString* string = + JS_NewUCStringCopyN(aCx, type.get(), type.Length()); + + intermediate = JS::StringValue(string); + hasProp = true; + } else { + RefPtr<File> file = blob->ToFile(); + if (file) { + if (token.EqualsLiteral("name")) { + nsString name; + file->GetName(name); + + JSString* string = + JS_NewUCStringCopyN(aCx, name.get(), name.Length()); + + intermediate = JS::StringValue(string); + hasProp = true; + } else if (token.EqualsLiteral("lastModified")) { + ErrorResult rv; + int64_t lastModifiedDate = file->GetLastModified(rv); + MOZ_ALWAYS_TRUE(!rv.Failed()); + + intermediate = JS_NumberValue(lastModifiedDate); + hasProp = true; + } else if (token.EqualsLiteral("lastModifiedDate")) { + ErrorResult rv; + Date lastModifiedDate = file->GetLastModifiedDate(rv); + MOZ_ALWAYS_TRUE(!rv.Failed()); + + lastModifiedDate.ToDateObject(aCx, &intermediate); + hasProp = true; + } + } + } + } + } + if (hasProp) { // Treat explicitly undefined as an error. if (intermediate.isUndefined()) { return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; diff --git a/dom/xbl/nsXBLBinding.cpp b/dom/xbl/nsXBLBinding.cpp index d9a2aacc5..b8174f6c2 100644 --- a/dom/xbl/nsXBLBinding.cpp +++ b/dom/xbl/nsXBLBinding.cpp @@ -1049,7 +1049,8 @@ nsXBLBinding::DoInitJSClass(JSContext *cx, // to create and define it. JS::Rooted<JSObject*> proto(cx); JS::Rooted<JS::PropertyDescriptor> desc(cx); - if (!JS_GetOwnUCPropertyDescriptor(cx, holder, aClassName.get(), &desc)) { + if (!JS_GetOwnUCPropertyDescriptor(cx, holder, aClassName.get(), + aClassName.Length(), &desc)) { return NS_ERROR_OUT_OF_MEMORY; } *aNew = !desc.object(); diff --git a/dom/xbl/nsXBLProtoImpl.cpp b/dom/xbl/nsXBLProtoImpl.cpp index 4db9cabf0..5efcb71e0 100644 --- a/dom/xbl/nsXBLProtoImpl.cpp +++ b/dom/xbl/nsXBLProtoImpl.cpp @@ -100,11 +100,15 @@ nsXBLProtoImpl::InstallImplementation(nsXBLPrototypeBinding* aPrototypeBinding, // end up with a different content prototype, but we'll already have a property // holder called |foo| in the XBL scope. Check for that to avoid wasteful and // weird property holder duplication. - const char16_t* className = aPrototypeBinding->ClassName().get(); + const nsString& className = aPrototypeBinding->ClassName(); + const char16_t* classNameChars = className.get(); + const size_t classNameLen = className.Length(); + JS::Rooted<JSObject*> propertyHolder(cx); JS::Rooted<JS::PropertyDescriptor> existingHolder(cx); if (scopeObject != globalObject && - !JS_GetOwnUCPropertyDescriptor(cx, scopeObject, className, &existingHolder)) { + !JS_GetOwnUCPropertyDescriptor(cx, scopeObject, classNameChars, + classNameLen, &existingHolder)) { return NS_ERROR_FAILURE; } bool propertyHolderIsNew = !existingHolder.object() || !existingHolder.value().isObject(); @@ -119,8 +123,8 @@ nsXBLProtoImpl::InstallImplementation(nsXBLPrototypeBinding* aPrototypeBinding, // Define it as a property on the scopeObject, using the same name used on // the content side. - bool ok = JS_DefineUCProperty(cx, scopeObject, className, -1, propertyHolder, - JSPROP_PERMANENT | JSPROP_READONLY, + bool ok = JS_DefineUCProperty(cx, scopeObject, classNameChars, classNameLen, + propertyHolder, JSPROP_PERMANENT | JSPROP_READONLY, JS_STUBGETTER, JS_STUBSETTER); NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED); } else { diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 85a38bba4..37d023bd4 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -2003,10 +2003,10 @@ JS_GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, const char* name, } JS_PUBLIC_API(bool) -JS_GetOwnUCPropertyDescriptor(JSContext* cx, HandleObject obj, const char16_t* name, +JS_GetOwnUCPropertyDescriptor(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, MutableHandle<PropertyDescriptor> desc) { - JSAtom* atom = AtomizeChars(cx, name, js_strlen(name)); + JSAtom* atom = AtomizeChars(cx, name, namelen); if (!atom) return false; RootedId id(cx, AtomToId(atom)); @@ -2028,7 +2028,19 @@ JS_GetPropertyDescriptor(JSContext* cx, HandleObject obj, const char* name, if (!atom) return false; RootedId id(cx, AtomToId(atom)); - return atom && JS_GetPropertyDescriptorById(cx, obj, id, desc); + return JS_GetPropertyDescriptorById(cx, obj, id, desc); +} + +JS_PUBLIC_API(bool) +JS_GetUCPropertyDescriptor(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, + MutableHandle<PropertyDescriptor> desc) +{ + JSAtom* atom = AtomizeChars(cx, name, namelen); + if (!atom) { + return false; + } + RootedId id(cx, AtomToId(atom)); + return JS_GetPropertyDescriptorById(cx, obj, id, desc); } static bool diff --git a/js/src/jsapi.h b/js/src/jsapi.h index c1195cc00..30c4a835a 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2917,7 +2917,7 @@ JS_GetOwnPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* nam JS::MutableHandle<JS::PropertyDescriptor> desc); extern JS_PUBLIC_API(bool) -JS_GetOwnUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name, +JS_GetOwnUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, JS::MutableHandle<JS::PropertyDescriptor> desc); /** @@ -2934,6 +2934,10 @@ extern JS_PUBLIC_API(bool) JS_GetPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* name, JS::MutableHandle<JS::PropertyDescriptor> desc); +extern JS_PUBLIC_API(bool) +JS_GetUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, + JS::MutableHandle<JS::PropertyDescriptor> desc); + /** * Define a property on obj. * |