[?-gad29939] heap-use-after-free for dynamic lights
Posted: Sun Dec 25, 2016 22:57
I could reproduce this by loading doom2 map01 with skill 4, warp to position 1135,700 and wait that the imp on the elevator on the left fires a fireball. At a certain point I got this:
[spoiler][/spoiler]
At the beginning I saw this with QZDoom with the new dynlights feature, then I found out it happens also in GZDoom.
I think there are some problems with the function ADynamicLight::CollectWithinRadius: 1) the inner loop with the subsector numlines has the same counter variable name as the main loop, 2) 'pos' can be invalidated when the collected_ss array pushes a new element and that's what the address sanitizer doesn't like.
[edit] Should be fixed with this PR, but I didn't check other situations involving lights.
Spoiler: Address sanitizer errorHere's the relevant backtrace from gdb:
[spoiler]
Code: Select all
#7 0x0000000000924c26 in ADynamicLight::DistToSeg (this=0x61a0007bd280, pos=..., seg=0x631000a7a9c0) at /home/edward-san/zdoom/gzdoom/trunk/src/gl/dynlights/a_dynlight.cpp:565
u = 6.953355807072167e-310
px = 6.953355807072167e-310
py = 2.3266681684861985e-316
seg_dx = -88
seg_dy = 0
seg_length_sq = 7744
#8 0x0000000000925373 in ADynamicLight::CollectWithinRadius (this=0x61a0007bd280, opos=..., subSec=0x629000ba4aa0, radius=16384) at /home/edward-san/zdoom/gzdoom/trunk/src/gl/dynlights/a_dynlight.cpp:617
seg = 0x631000a7a9c0
i = 1
pos = @0x615000148108: {X = 668.4408339551361, Y = 687.36427712208331, Z = 124.35780188949346}
sec = 0x62d0020e7c10
i = 8
#9 0x0000000000926605 in ADynamicLight::LinkLight (this=0x61a0007bd280) at /home/edward-san/zdoom/gzdoom/trunk/src/gl/dynlights/a_dynlight.cpp:725
subSec = 0x629000ba6840
node = 0x0
#10 0x00000000009241d0 in ADynamicLight::UpdateLocation (this=0x61a0007bd280) at /home/edward-san/zdoom/gzdoom/trunk/src/gl/dynlights/a_dynlight.cpp:426
oldx = 658.50681053643609
oldy = 687.0952360740946
oldradius = 128
intensity = 64
__PRETTY_FUNCTION__ = "void ADynamicLight::UpdateLocation()"
#11 0x0000000000923788 in ADynamicLight::Tick (this=0x61a0007bd280) at /home/edward-san/zdoom/gzdoom/trunk/src/gl/dynlights/a_dynlight.cpp:365
No locals.
#12 0x0000000000c16abc in AF_DThinker_Tick (param=0x7fffffffc7e0, defaultparam=..., numparam=1, ret=0x0, numret=0) at /home/edward-san/zdoom/gzdoom/trunk/src/dthinker.cpp:549
paramnum = <error reading variable paramnum (Cannot access memory at address 0xffffffffffffffc0)>
__PRETTY_FUNCTION__ = "int AF_DThinker_Tick(VMValue*, TArray<VMValue>&, int, VMReturn*, int)"
self = 0x61a0007bd280
#13 0x0000000001321af9 in VMFrameStack::Call (this=0x7ffff7f30928, func=0x60800002be20, params=0x7fffffffc7e0, numparams=1, results=0x0, numresults=0, trap=0x0) at /home/edward-san/zdoom/gzdoom/trunk/src/scripting/vm/vmframe.cpp:462
__PRETTY_FUNCTION__ = "int VMFrameStack::Call(VMFunction*, VMValue*, int, VMReturn*, int, VMException**)"
allocated = false
#14 0x0000000000c16ce6 in DThinker::CallTick (this=0x61a0007bd280) at /home/edward-san/zdoom/gzdoom/trunk/src/dthinker.cpp:559
params = {{{i = 8114816, {a = 0x61a0007bd280, atag = 1}, f = 5.3032922817055894e-310, {pad = {8114816, 24992, 1}, Type = 3 '\003'}, biggest = {foo = {8114816, 24992, 1, 3}}}}}
VIndex = 0
__PRETTY_FUNCTION__ = "void DThinker::CallTick()"
clss = 0x615000000d00
func = 0x60800002be20
#15 0x0000000000c1677c in DThinker::TickThinkers (list=0x2d22ac0 <DThinker::Thinkers+512>, dest=0x0) at /home/edward-san/zdoom/gzdoom/trunk/src/dthinker.cpp:527
count = 11
node = 0x61a0007bd280
At the beginning I saw this with QZDoom with the new dynlights feature, then I found out it happens also in GZDoom.
I think there are some problems with the function ADynamicLight::CollectWithinRadius: 1) the inner loop with the subsector numlines has the same counter variable name as the main loop, 2) 'pos' can be invalidated when the collected_ss array pushes a new element and that's what the address sanitizer doesn't like.
[edit] Should be fixed with this PR, but I didn't check other situations involving lights.