зеркало из https://github.com/mozilla/gecko-dev.git
Bug 981036. Disallow calling DOM constructors as functions in non-release builds. r=bholley
This commit is contained in:
Родитель
51c7e3a485
Коммит
b5d04164e0
|
@ -867,6 +867,12 @@ ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp)
|
|||
return ThrowErrorMessage(cx, MSG_ILLEGAL_CONSTRUCTOR);
|
||||
}
|
||||
|
||||
bool
|
||||
ThrowConstructorWithoutNew(JSContext* cx, const char* name)
|
||||
{
|
||||
return ThrowErrorMessage(cx, MSG_CONSTRUCTOR_WITHOUT_NEW, name);
|
||||
}
|
||||
|
||||
inline const NativePropertyHooks*
|
||||
GetNativePropertyHooks(JSContext *cx, JS::Handle<JSObject*> obj,
|
||||
DOMObjectType& type)
|
||||
|
|
|
@ -117,6 +117,7 @@ ThrowMethodFailedWithDetails(JSContext* cx, ErrorResult& rv,
|
|||
}
|
||||
if (rv.IsNotEnoughArgsError()) {
|
||||
rv.ReportNotEnoughArgsError(cx, ifaceName, memberName);
|
||||
return false;
|
||||
}
|
||||
return Throw(cx, rv.ErrorCode());
|
||||
}
|
||||
|
@ -1466,6 +1467,9 @@ WantsQueryInterface
|
|||
bool
|
||||
ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool
|
||||
ThrowConstructorWithoutNew(JSContext* cx, const char* name);
|
||||
|
||||
// vp is allowed to be null; in that case no get will be attempted,
|
||||
// and *found will simply indicate whether the property exists.
|
||||
bool
|
||||
|
|
|
@ -1183,26 +1183,43 @@ class CGClassConstructor(CGAbstractStaticMethod):
|
|||
|
||||
def generate_code(self):
|
||||
preamble = """
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
JS::Rooted<JSObject*> obj(cx, &args.callee());
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
JS::Rooted<JSObject*> obj(cx, &args.callee());
|
||||
"""
|
||||
# [ChromeOnly] interfaces may only be constructed by chrome.
|
||||
# Additionally, we want to throw if a non-chrome caller does a bareword invocation of a
|
||||
# constructor without |new|. We don't enforce this for chrome to avoid the addon compat
|
||||
# fallout of making that change. See bug 916644.
|
||||
if isChromeOnly(self._ctor):
|
||||
mayInvokeCtor = "nsContentUtils::ThreadsafeIsCallerChrome()"
|
||||
preamble += (
|
||||
"if (!nsContentUtils::ThreadsafeIsCallerChrome()) {\n"
|
||||
" return ThrowingConstructor(cx, argc, vp);\n"
|
||||
"}\n\n")
|
||||
|
||||
# Additionally, we want to throw if a caller does a bareword invocation
|
||||
# of a constructor without |new|. We don't enforce this for chrome in
|
||||
# realease builds to avoid the addon compat fallout of making that
|
||||
# change. See bug 916644.
|
||||
name = self._ctor.identifier.name
|
||||
if name != "constructor":
|
||||
ctorName = name
|
||||
else:
|
||||
mayInvokeCtor = "(args.isConstructing() || nsContentUtils::ThreadsafeIsCallerChrome())"
|
||||
preamble += """ if (!%s) {
|
||||
return ThrowingConstructor(cx, argc, vp);
|
||||
}
|
||||
""" % mayInvokeCtor
|
||||
ctorName = self.descriptor.interface.identifier.name
|
||||
preamble += (
|
||||
"bool mayInvoke = args.isConstructing();\n"
|
||||
"#ifdef RELEASE_BUILD\n"
|
||||
"mayInvoke = mayInvoke || nsContentUtils::ThreadsafeIsCallerChrome();\n"
|
||||
"#endif // RELEASE_BUILD\n"
|
||||
"if (!mayInvoke) {\n"
|
||||
" // XXXbz wish I could get the name from the callee instead of\n"
|
||||
" // Adding more relocations\n"
|
||||
' return ThrowConstructorWithoutNew(cx, "%s");\n'
|
||||
"}" % ctorName)
|
||||
|
||||
name = self._ctor.identifier.name
|
||||
nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
|
||||
callGenerator = CGMethodCall(nativeName, True, self.descriptor,
|
||||
self._ctor, isConstructor=True)
|
||||
return preamble + callGenerator.define();
|
||||
self._ctor, isConstructor=True,
|
||||
constructorName=ctorName)
|
||||
return CGList([CGIndenter(CGGeneric(preamble)), callGenerator],
|
||||
"\n").define()
|
||||
|
||||
# Encapsulate the constructor in a helper method to share genConstructorBody with CGJSImplMethod.
|
||||
class CGConstructNavigatorObjectHelper(CGAbstractStaticMethod):
|
||||
|
@ -5420,9 +5437,13 @@ class CGMethodCall(CGThing):
|
|||
signatures and generation of a call to that signature.
|
||||
"""
|
||||
def __init__(self, nativeMethodName, static, descriptor, method,
|
||||
isConstructor=False):
|
||||
isConstructor=False, constructorName=None):
|
||||
CGThing.__init__(self)
|
||||
|
||||
if isConstructor:
|
||||
assert constructorName is not None
|
||||
methodName = constructorName
|
||||
else:
|
||||
methodName = "%s.%s" % (descriptor.interface.identifier.name, method.identifier.name)
|
||||
argDesc = "argument %d of " + methodName
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ MSG_DEF(MSG_SETTER_THIS_UNWRAPPING_DENIED, 1, "Permission to call '{0}' setter d
|
|||
MSG_DEF(MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 1, "\"this\" object does not implement interface {0}.")
|
||||
MSG_DEF(MSG_NOT_IN_UNION, 2, "{0} could not be converted to any of: {1}.")
|
||||
MSG_DEF(MSG_ILLEGAL_CONSTRUCTOR, 0, "Illegal constructor.")
|
||||
MSG_DEF(MSG_CONSTRUCTOR_WITHOUT_NEW, 1, "Constructor {0} requires 'new'")
|
||||
MSG_DEF(MSG_NO_INDEXED_SETTER, 1, "{0} doesn't have an indexed property setter.")
|
||||
MSG_DEF(MSG_NO_NAMED_SETTER, 1, "{0} doesn't have a named property setter.")
|
||||
MSG_DEF(MSG_ENFORCE_RANGE_NON_FINITE, 1, "Non-finite value is out of range for {0}.")
|
||||
|
|
Загрузка…
Ссылка в новой задаче