aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4generatorobject.cpp
Commit message (Collapse)AuthorAgeFilesLines
* CRA review qml/jsruntimeFabian Kosmale2025-09-161-0/+1
| | | | | | | | | | | | | | | | | | This relies heavily on the documented fact that we only support trusted QML/JS content, meaning most files are only significant, not critical. This also extends to the handling of qmlc files (as in compilationunitmapper), as we store them in a user owned, non-shared cache directory – so any vulnerability there would already mean that an attacker has write-priviledges on user data. An exception is ArrayBuffer, which can be used with arbitrary user data, and should create a valid QBA. Fixes: QTBUG-136970 Pick-to: 6.10 6.9 6.8 QUIP: 23 Change-Id: I22033fe6ab4acf8362a8183e25b92331d45cb32c Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QJSEngine: Check for stack overflows on generatorsLuca Di Sera2024-08-261-9/+20
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Generally, the engine checks for stack overflows each time a function is called. In the common case, the entry point for the execution of a function is `QV4::Moth::VME::exec`, which will perform the check as part of its execution. `exec` will then dispatch to the execution of the function, either by using the JIT when enabled and available or by calling `QV4::Moth::VME::interpret` when this is not the case. Generators work slightly differently than a normal call, both when a Generator Function or Method is executed and when a generator is resumed. In particular, the execution of a Generator Function or Method and the execution of a resumed generator do not pass by `exec`, instead directly calling `interpret`on the relevant code. As `interpret` does not perform any check for stack overflows, a call to a Generator Function or Method or the processing of a resume operation on a Generator will not identify those overflows, such that it will fail to throw a `RangeError`, as it would be normal for a normal call, instead ending up segfaulting down the call chain. To avoid the issue, ensure that a check for stack overflows is performed before a call to `interpret` in both `GeneratorFunction::virtualCall` and `GeneratorObject::resume`, to ensure that an exception is thrown when required. The ordering of operations for `resume` was modified to allow for the abrupt return due to the, now possible, stack overflow exception. Both `return` and `throw` can produce a resume of the generator and both of them throw an exception in doing so. `return` throws an exception as an implementation detail. An `emptyValue` is thrown, which will later be recognized by the execution of a `Resume` instruction and cleaned away. Failure to do the cleaning will produce an issue as an `emptyValue` should not propagate through the system. `throw` throws as part of its implementation as expected by the spec. As both throws are performed before resume is called, the thrown value would hide the `RangeError` exception that can be thrown due to a stack overflow. To allow for the stack overflow to be correctly recognized and its thrown error not to be hidden, `resume` was modified to accept a third optional parameter, representing a value to be thrown just before calling `interpret` and after checking for a stack overflow. Its call site in `method_next`, `method_return` and `method_throw` were modified accordingly. Some test-cases were added to `tst_qjsengine` to ensure that the correct kind of exception is thrown when a stack overflow happens on the execution of a Generator Function or Method or when resuming a Generator. Pick-to: 6.7 6.8 Fixes: QTBUG-127049 Change-Id: I3656957097df3ccd5c6d70f86335bc40e229bb20 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* V4: Slim down FunctionObjectUlf Hermann2024-05-141-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Most FunctionObjects do not actually need their custom jsCall members. They will only call the functions from the vtable anyway. FunctionObject can therefore be split into a static and a dynamic variant. Only the dyanmic variant needs to carry (and invoke) the extra pointer. The jsCallWithMetaTypes pointer is completely pointless because none of the dynamic functions actually implement it. Furthermore, the QV4::Function and QV4::ExecutionContext pointers in FunctionObject are only needed by actual JavaScript functions. The builtins that like to be dynamic functions never need them. Therefore, split out another class for this. In the generic FunctionObject, we need the capability to decide at run time whether the function shall be a constructor or not. Add a flag to replace the check for jsCallAsConstructor. Also, where we can, avoid the pessimization of checking whether a function is a constructor before trying to call it as constructor. Rather have the default implementation throw the exception. As a side effect, for most functions we don't need an ExecutionContext anymore. The engine is enough. Task-number: QTBUG-124662 Change-Id: Iac657fa71288dd6ec230a33de2986ba3bcf4628c Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Always link executable CU on creationUlf Hermann2024-01-101-1/+1
| | | | | | | | | | | | | | | We don't want floating unlinked executable CUs. They should always be tied to an engine, and the engine should not change. This gives us one definite point where to register them with the engine (to be done in subsequent change). Unfortunately, due to the refcounting, we need to remove the engine from any still-referenced CUs when the engine itself is destructed. We will be able to drop the refcounting and make the engine fully own its executable CUs once we can hold base CUs in most places. Change-Id: I9a53e83d5c4746c2b2bca896b51baa4fe7fee757 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* qv4mm: Document and extend allocManaged overload setFabian Kosmale2023-10-061-1/+1
| | | | | | | | | Add some helper overloads to centralize the sizeof computation. Add a doc note about the various variants of allocManaged, including a note why we even need the size parameter. Change-Id: I4e0c485217e87c339a7433c306cb05d6614d30e1 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Use SPDX license identifiersLucie Gérard2022-06-111-38/+2
| | | | | | | | | | | | Replace the current license disclaimer in files by a SPDX-License-Identifier. Files that have to be modified by hand are modified. License files are organized under LICENSES directory. Pick-to: 6.4 Task-number: QTBUG-67283 Change-Id: I63563bbeb6f60f89d2c99660400dca7fab78a294 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* Fix missing whitespace after `argv[N]:` patternIvan Tkachenko2021-10-071-2/+2
| | | | | Change-Id: I6657ffd1e29124211642c62f719057cfe9b2aa6c Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Eliminate JS call frame from metatypes callsUlf Hermann2021-06-101-1/+2
| | | | | | | | If we call an AOT-compiled function we never need the JavaScript call frame. We can just skip its setup and save some overhead. Change-Id: I39dc2ca6eea5b5a66f3b87b642a310534cecf6cd Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Optimize stack frame setup for AOT compiled functionsUlf Hermann2021-03-231-11/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When called via the metaobject system, parameters and return values are passed as void*, with accompanying type information in the form of QMetaType. The same format is expected when calling an AOT compiled function. Previously, we would first convert all the parameters to QV4::Value, just to convert them back the moment we notice that there is an AOT compiled function. This is wasteful. This change provides a second call infrastructure that accepts void* and QMetaType as parameter and return value format, and passes them as-is all the way to any AOT compiled functions. If there is no AOT compiled function, the conversion is done when detecting this, rather than when initiating the call. This also passes the information "ignore return value" all the way down to the actual function call. If the caller is not interested in the return value, we don't have to marshal it back at all. For now, we only add the extra "callWithMetaTypes" vtable entry to ArrowFunction. However, other callables could also receive variants optimized for calling with void*/int rather than V4 values. This required changing the way how function arguments are stored in the property cache. We squeeze the return type into QQmlPropertyCacheMethodArguments now, and we use QMetaType instead of integers. In turn, we remove some unused bits. Change-Id: I946e603e623d9d985c54d3a15f6f4b7c7b7d8c60 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* qv4generatorobject: Fix crash when creating new propertiesMaximilian Goldstein2021-03-081-12/+9
| | | | | | | | | | | | | | | | Previously HeapObject::GeneratorObject utilized a ValueArray member to store stack information. As we rely on all HeapObject members to have a constant size in order for QV4Table::inlinePropertyOffset to remain accurate, this lead to a memory conflict when a user defined his own property on the Generator. Please do not use ValueArray for any types that are user accessible or that you intend to add properties to. Now the stack information is stored into ArrayObjects instead which circumvents the issue. Fixes: QTBUG-91491 Pick-to: 5.15 6.0 6.1 Change-Id: Id6f638bf36a3ae3c9320ac99e67214c48dc81226 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
* Split CompiledData::CompilationUnit in twoUlf Hermann2019-05-161-1/+1
| | | | | | | | We need a CompilationUnit that only holds the data needed for compilation and another one that is executable by the runtime. Change-Id: I704d859ba028576a18460f5e3a59f210f64535d3 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Scope intermediate values when allocating objectsUlf Hermann2019-03-271-1/+3
| | | | | | | | | Otherwise the garbage collector might interfere and we might end up with dangling pointers in random places. Task-number: QTBUG-74190 Change-Id: I253c526ef930b8f0be14e96a42af8b66fda3b22d Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Ensure our builtin constructors are subclassableLars Knoll2018-11-221-2/+9
| | | | | | | | | Respect the newTarget passed into those constructors and make sure we set up the proto chain correctly. Change-Id: I3d12c7dbef4b33660a6715d73e9fb0f89105167a Fixes: QTBUG-71138 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
* Cleanups in Value/PrimitiveLars Knoll2018-09-171-10/+10
| | | | | | | | | | | | Get rid of Primitive and move the corresponding methods directly into Value. Mark many methods in Value as constexpr and turn Value into a POD type again. Keep Primitive as a pure alias to Value for source compatibility of other modules that might be using it. Change-Id: Icb47458947dd3482c8852e95782123ea4346f5ec Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Add support for yield*Lars Knoll2018-09-071-0/+3
| | | | | Change-Id: I5b054b59519ed825459a5b0b0a7cd2c6fc8a3797 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Fix super property accessLars Knoll2018-08-311-2/+8
| | | | | | | | | Super properties work in a rather special way by accessing a 'home object' on the function object, and reading from it's prototype. Change-Id: I666334c9c27048c6c2ba6770dd8c9f56aecbee14 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Implement IsConstructor for Function objectsLars Knoll2018-08-231-10/+0
| | | | | | | | Use the jsConstruct member in the function object for this and set it to a nullptr for methods that are not a constructor. Change-Id: I63d2971b23b2596a8e3b6d2781f0d9ed3208693b Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Fix naming of methods defined in object or class literalsLars Knoll2018-08-011-2/+2
| | | | | Change-Id: I01b7774097a447520c85ae6766e6ca1162e921ba Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Fix class members that are generatorsLars Knoll2018-07-031-0/+18
| | | | | | | Properly support member functions that are generators in classes. Change-Id: I5fc8d5b58a17c61a446b43d6576bb83de5ecd920 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Refactor initialization code for JS stack framesLars Knoll2018-07-031-23/+9
| | | | | | | | | Move code into qv4stackframe_p.h, so that it can be re-used from different places. Clean up VME::exec and the generatorfunctions using this. Change-Id: Ib4f7eceeb5f55d98dd6ccf2584d13a3b864caea1 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Smaller refactoring of VME::exec() to preapre for upcoming changesLars Knoll2018-07-031-2/+2
| | | | | | | | | We'll need a more flexible interface here to support derived constructors properly. There's also quite some code in the generator functions that could benefit from some cleanups. Change-Id: I951b5d2171efa80d52fd6b0155f8f2c78af2f3b5 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Implement support for new.targetLars Knoll2018-07-031-3/+3
| | | | | | | | | Support the new.target meta property in the codegen, and add support for passing the newtarget into the constructor vtable methods and the execution context. Change-Id: I62ea58e5e92d894035a76e35776203e9837c383b Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Prefix vtable methods with virtualLars Knoll2018-07-031-5/+5
| | | | | | | | | Turns out that the overloading of vtable methods and regular ones is problematic in some cases. So let's rather make it explicit which methods are part of the vtable, and which aren't. Change-Id: Ifee32a26104d30f3c82bca8b5a9cdea2d4f4f526 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Add Proxy support for prototype handlingLars Knoll2018-06-251-4/+4
| | | | | | | | | | | | | | Cleanup get/setPrototypeOf and fix some smaller incompatibilities in the default implementation for Object. Add the methods to the vtable and reimplement them according to spec for ProxyObjects. Clean up the Object.prototype.get/setPrototypeOf/__proto__ methods and fix a smaller bug in the Reflect API for those methods. Change-Id: I6e438753332ec4db963d6cdcf86f340ff212777a Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Minor cleanup with bytecode pointer typesSimon Hausmann2018-05-281-1/+1
| | | | | | | | | | | | Even though we consider the bytecode to be a sequence of unsigned bytes, we store it as const char * (so unsigned except on arm) everywhere, because that makes it convenient to work with QByteArray's constData(). By using const char * consistently we can get rid of at least one more reinterpret_cast. Change-Id: I7a803e4201381c39eec2fdc6497d9bf36a1c2b6b Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Fix the prototype of the Generator prototype objectLars Knoll2018-05-131-0/+1
| | | | | | | It should inherit from IteratorProto. Change-Id: I8494047204782e64be96d1ae6f5034c476f770ad Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Ensure we have a lexical scope for global codeLars Knoll2018-05-111-1/+1
| | | | | | | | | | | | | | | This requires a bit more work than simply pushing a new BlockContext for the lexically declared variables, as eval() and the Function constructor operate on the global scope (including the lexically declared names). To fix this introduce Push/PopScriptContext instructions, that create a BlockContext for the lexically declared vars and pushes that one as a global script context that eval and friends use. Change-Id: I0fd0b0f682f82e250545e874fe93978449fe5e46 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Add Generator supportLars Knoll2018-05-031-0/+247
Add support for ES6 generators. Those are currently always executed in the interpreter (we never JIT them), to simplify the initial implementation. Most functionality, except for 'yield *' expressions are supported. 'yield *' will have to wait until we support for(... of ...) Change-Id: I7c059d1e3b301cbcb79e3746b4bec346738fd426 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>