aboutsummaryrefslogtreecommitdiffstats
path: root/src/particles/qquickitemparticle.cpp
diff options
context:
space:
mode:
authorLuca Di Sera <[email protected]>2025-07-01 14:39:35 +0200
committerLuca Di Sera <[email protected]>2025-07-03 19:24:23 +0200
commit64b3748b39db6241a914da8c358d245061977409 (patch)
tree591b7b3f423e2516bfaa076f51dc0227241f538b /src/particles/qquickitemparticle.cpp
parent23df452196c165ee8fbc7a4efc82a357bca5ca16 (diff)
Avoid accessing garbage memory on the js stackHEADdev
When allocating an object on the JS heap the garbage collector might be run as part of the allocation, in particular as a way to possibly make space when the memory space is starting to get filled up. When the garbage collector runs, it is possible, as part of its normal processing, that it will access the JS stack, and try to interact with the objects that are stored on it. In particular, while collecting from the JS stack, the garbage collector will need to mark all Managed objects that are found on it. When allocating on the JS stack it is possible that the allocation and the initialization of the allocated memory are performed in separate steps. When this is so, it is possible for the allocated element on the stack to represent garbage memory in between being allocated and being initialized. Since the garbage collector can inspect all elements on the stack as part of its processing, it is possible for it to inspect an element that represents garbage memory if it runs in between the allocation and initialization of that stack element. Furthermore, since each allocation might run the garbage collector, then any allocation in between the allocation and initialization of such a stack element can access garbage memory. In particular, if the garbage memory represents a pointer to a previously existing Managed object that was swept, the garbage collector might try to mark an object that shouldn't be marked. There are a few cases of this currently in the code-base. While instantiating a QML file, `QQmlObjectCreator` keeps track of objects that are created in the process, to avoid premature collection. As part of this, `ObjectInCreationGCAnchoList::trackObject` will be called, in turn allocating on an element on the js stack and then initializing it separately by the creation of `QObjectWrapper`. The creation of a `QObjectWrapper` generally allocates, such that it can incur into the above problem. As part of dealing with the JS spread operator, in particular when processing the spread element, we juggle with multiple allocation of uninitialized elements on the js stack. During this processing multiple part of the code can allocate. For example, the spread element is handled through the use of an iterator that, during its creation, might allocate as during the creation process we might convert the spread argument to object so that the iterator can deal with it, which would be the case for a spread argument that is a string. When allocating an element on the js stack that is bound to a certain scope, we sometime allow a conversion to be performed on the original element. This conversion routine might allocate, and it does do so for the currently existing conversion to a String and to an Object. The conversion routine is called after an uninitialized element is pushed on the stack, and can thus incur into the above issue. To fix the issue, an additional method was added, `construct`, that ensures that allocation and initialization happen sequentially with no allocation in-between, using an initialization value that is passed as an argument. The new method was applied to the code affected by the bug, in practice, reordering the operations in the affected cases such that the bug-producing allocations happens before the allocation on the stack such as to avoid the bug while keeping the same semantics. An exception was taken for the handling of the spread argument, which has a more complex control flow, where the solution that was used is to initialize the memory to the empty value as part of the allocation. A series of test cases showing an example of the issues were added to `tst_qv4mm`. The tests make use of the fact that we assert when we find a Managed object on the js stack that is not in use, as that is a logical error for the garbage collector, to observe the issue and are thus skipped when assertions are not enabled. Change-Id: Id478e16ee22e20e77d01fdfae9a0269d6d709892 Reviewed-by: Ulf Hermann <[email protected]>
Diffstat (limited to 'src/particles/qquickitemparticle.cpp')
0 files changed, 0 insertions, 0 deletions