Bug 981036. Disallow calling DOM constructors as functions in non-release builds. r=bholley

This commit is contained in:
Boris Zbarsky 2014-03-10 17:38:31 -04:00
Родитель 51c7e3a485
Коммит b5d04164e0
4 изменённых файлов: 47 добавлений и 15 удалений

Просмотреть файл

@ -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,10 +5437,14 @@ 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)
methodName = "%s.%s" % (descriptor.interface.identifier.name, method.identifier.name)
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
def requiredArgCount(signature):

Просмотреть файл

@ -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}.")