From 7f3436363388af9e9fe5c8578dee8997c078bb16 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 11 May 2021 17:53:09 +0200 Subject: Cycles X: Fix possible use of uninitialized ShaderClosure It is possible that BSDF allocation will advance pointer in the allocation "pool" but will return null pointer if the weight is too small. One artist-measurable issue this change fixes is random issues with denoising: normal pass for denoising could have accessed non-initialized normal of a closure. Differential Revision: https://developer.blender.org/D11230 --- intern/cycles/kernel/closure/alloc.h | 44 ++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) (limited to 'intern/cycles') diff --git a/intern/cycles/kernel/closure/alloc.h b/intern/cycles/kernel/closure/alloc.h index 341d1e16eb1..5b74a868e72 100644 --- a/intern/cycles/kernel/closure/alloc.h +++ b/intern/cycles/kernel/closure/alloc.h @@ -57,14 +57,22 @@ ccl_device ccl_addr_space void *closure_alloc_extra(ShaderData *sd, int size) ccl_device_inline ShaderClosure *bsdf_alloc(ShaderData *sd, int size, float3 weight) { - ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight); + const float sample_weight = fabsf(average(weight)); - if (sc == NULL) - return NULL; + /* Use comparison this way to help dealing with non-finite weight: if the average is not finite + * we will not allocate new closure. */ + if (sample_weight >= CLOSURE_WEIGHT_CUTOFF) { + ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight); + if (sc == NULL) { + return NULL; + } + + sc->sample_weight = sample_weight; - float sample_weight = fabsf(average(weight)); - sc->sample_weight = sample_weight; - return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? sc : NULL; + return sc; + } + + return NULL; } #ifdef __OSL__ @@ -73,17 +81,25 @@ ccl_device_inline ShaderClosure *bsdf_alloc_osl(ShaderData *sd, float3 weight, void *data) { - ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight); + const float sample_weight = fabsf(average(weight)); - if (!sc) - return NULL; + /* Use comparison this way to help dealing with non-finite weight: if the average is not finite + * we will not allocate new closure. */ + if (sample_weight >= CLOSURE_WEIGHT_CUTOFF) { + ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight); + if (!sc) { + return NULL; + } - memcpy((void *)sc, data, size); + memcpy((void *)sc, data, size); - float sample_weight = fabsf(average(weight)); - sc->weight = weight; - sc->sample_weight = sample_weight; - return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? sc : NULL; + sc->weight = weight; + sc->sample_weight = sample_weight; + + return sc; + } + + return NULL; } #endif -- cgit v1.2.3