Fix #37192, Rendered preview causes crash when deleting a material node in shader node editor. The 'free' callback for node execution data was accessed from the node->typeinfo, but this pointer can

become invalid because the render database is not immediately freed after the job finishes. To avoid access to dangling node pointers, store the function callback in the exec data itself. The node
pointer must not be accessed in the free function (wasn't used before either), these functions are purely for the execution data.
This commit is contained in:
Lukas Toenne 2013-10-29 17:46:01 +00:00
parent 8d11abb0ec
commit 8bdbbca485
5 changed files with 8 additions and 6 deletions

View File

@ -132,7 +132,7 @@ typedef struct bNodeSocketType {
} bNodeSocketType;
typedef void *(*NodeInitExecFunction)(struct bNodeExecContext *context, struct bNode *node, bNodeInstanceKey key);
typedef void (*NodeFreeExecFunction)(struct bNode *node, void *nodedata);
typedef void (*NodeFreeExecFunction)(void *nodedata);
typedef void (*NodeExecFunction)(void *data, int thread, struct bNode *, struct bNodeExecData *execdata, struct bNodeStack **in, struct bNodeStack **out);
typedef int (*NodeGPUExecFunction)(struct GPUMaterial *mat, struct bNode *node, struct bNodeExecData *execdata, struct GPUNodeStack *in, struct GPUNodeStack *out);

View File

@ -207,6 +207,7 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNo
/* prepare all nodes for execution */
for (n = 0, nodeexec = exec->nodeexec; n < totnodes; ++n, ++nodeexec) {
node = nodeexec->node = nodelist[n];
nodeexec->freeexecfunc = node->typeinfo->freeexecfunc;
/* tag inputs */
for (sock = node->inputs.first; sock; sock = sock->next) {
@ -245,9 +246,8 @@ void ntree_exec_end(bNodeTreeExec *exec)
MEM_freeN(exec->stack);
for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
if (nodeexec->node->typeinfo)
if (nodeexec->node->typeinfo->freeexecfunc)
nodeexec->node->typeinfo->freeexecfunc(nodeexec->node, nodeexec->data.data);
if (nodeexec->freeexecfunc)
nodeexec->freeexecfunc(nodeexec->data.data);
}
if (exec->nodeexec)

View File

@ -51,6 +51,8 @@ struct bNodeStack;
typedef struct bNodeExec {
struct bNode *node; /* backpointer to node */
bNodeExecData data;
NodeFreeExecFunction freeexecfunc; /* free function, stored in exec itself to avoid dangling node pointer access */
} bNodeExec;
/* Execution Data for each instance of node tree execution */

View File

@ -85,7 +85,7 @@ static void *group_initexec(bNodeExecContext *context, bNode *node, bNodeInstanc
return exec;
}
static void group_freeexec(bNode *UNUSED(node), void *nodedata)
static void group_freeexec(void *nodedata)
{
bNodeTreeExec *gexec = (bNodeTreeExec *)nodedata;

View File

@ -72,7 +72,7 @@ static void *group_initexec(bNodeExecContext *context, bNode *node, bNodeInstanc
return exec;
}
static void group_freeexec(bNode *UNUSED(node), void *nodedata)
static void group_freeexec(void *nodedata)
{
bNodeTreeExec *gexec = (bNodeTreeExec *)nodedata;