"pointer being freed was not allocated" in TikZ_Close (tikzInfo->outColorFileName?)
p00ya opened this issue · 6 comments
Environment
macOS 10.15.1, tikzDevice 0.12.3
platform x86_64-apple-darwin18.7.0
arch x86_64
os darwin18.7.0
system x86_64, darwin18.7.0
status
major 3
minor 6.1
year 2019
month 07
day 05
svn rev 76782
language R
version.string R version 3.6.1 (2019-07-05)
nickname Action of the Toes
Repro
tikz(
foo,
onefile = FALSE,
timestamp = FALSE
)
print(bar)
dev.off()
Sorry I don't have a minimal bar
for you to repro - I can't tickle the crash consistently. However, I think the fix is obvious even without a repro ;)
Observed behaviour
Creating temporary TikZ metrics dictionary at:
/Volumes/ramdisk/Rtmpb9zShw/tikzMetricsDictionary
Using TikZ metrics dictionary at:
/Volumes/ramdisk/Rtmpb9zShw/tikzMetricsDictionary
Measuring dimensions of: \char77
Running command: '/Library/TeX/texbin/pdflatex' -interaction=batchmode -halt-on-error -output-directory '/Volumes/ramdisk/Rtmpb9zShw/tikzDevice10e765bc781c1' 'tikzStringWidthCalc.tex'
[... snip ...]
R(69238,0x116b9edc0) malloc: *** error for object 0x7fed65c638b0: pointer being freed was not allocated
R(69238,0x116b9edc0) malloc: *** set a breakpoint in malloc_error_break to debug
Notes
I'm pretty sure it's
free(tikzInfo->originalColorFileName);
from https://github.com/daqana/tikzDevice/blob/master/src/tikzDevice.c#L702
I compiled tikzDevice with CFLAGS = -O1 -arch x86_64 -g
to help with debugging.
Then after triggering the crash I attached lldb and disassembled the frame:
di -f -m
tikzDevice.so`TikZ_Close:
0x116959bc0 <+0>: pushq %rbp
0x116959bc1 <+1>: movq %rsp, %rbp
0x116959bc4 <+4>: pushq %rbx
0x116959bc5 <+5>: pushq %rax
0x116959bc6 <+6>: movq 0xb0(%rdi), %rbx
0x116959bcd <+13>: cmpl $-0x1, 0x88(%rbx)
0x116959bd4 <+20>: je 0x116959c0b ; <+75>
0x116959bd6 <+22>: cmpl $0x1, 0x50(%rbx)
0x116959bda <+26>: je 0x116959c2c ; <+108>
0x116959bdc <+28>: cmpl $-0x1, 0x8c(%rbx)
0x116959be3 <+35>: jne 0x116959c2c ; <+108>
0x116959be5 <+37>: leaq 0x2922(%rip), %rsi ; "\end{tikzpicture}\n"
0x116959bec <+44>: movq %rbx, %rdi
0x116959bef <+47>: xorl %eax, %eax
0x116959bf1 <+49>: callq 0x116959750 ; printOutput
0x116959bf6 <+54>: movl $0x0, 0x8c(%rbx)
0x116959c00 <+64>: cmpl $0x1, 0x4c(%rbx)
0x116959c04 <+68>: jne 0x116959c32 ; <+114>
0x116959c06 <+70>: jmp 0x116959cb0 ; <+240>
0x116959c0b <+75>: leaq 0x28ef(%rip), %rsi ; "\end{scope}\n"
0x116959c12 <+82>: movq %rbx, %rdi
0x116959c15 <+85>: xorl %eax, %eax
0x116959c17 <+87>: callq 0x116959750 ; printOutput
0x116959c1c <+92>: movl $0x0, 0x88(%rbx)
0x116959c26 <+102>: cmpl $0x1, 0x50(%rbx)
0x116959c2a <+106>: jne 0x116959bdc ; <+28>
0x116959c2c <+108>: cmpl $0x1, 0x4c(%rbx)
0x116959c30 <+112>: je 0x116959cb0 ; <+240>
0x116959c32 <+114>: cmpl $0x1, 0x48(%rbx)
0x116959c36 <+118>: je 0x116959cd9 ; <+281>
0x116959c3c <+124>: cmpl $0x0, 0x80(%rbx)
0x116959c43 <+131>: je 0x116959cfa ; <+314>
0x116959c49 <+137>: movq %rbx, %rdi
0x116959c4c <+140>: callq 0x11695b640 ; TikZ_WriteColorFile
0x116959c51 <+145>: movq 0x10(%rbx), %rdi
0x116959c55 <+149>: callq 0x11695c154 ; symbol stub for: free
0x116959c5a <+154>: cmpl $0x0, 0x54(%rbx)
0x116959c5e <+158>: jne 0x116959c69 ; <+169>
0x116959c60 <+160>: movq 0x18(%rbx), %rdi
0x116959c64 <+164>: callq 0x11695c154 ; symbol stub for: free
0x116959c69 <+169>: movq 0x98(%rbx), %rdi
0x116959c70 <+176>: callq 0x11695c154 ; symbol stub for: free
0x116959c75 <+181>: movq 0x20(%rbx), %rdi
0x116959c79 <+185>: callq 0x11695c154 ; symbol stub for: free
-> 0x116959c7e <+190>: movq 0x28(%rbx), %rdi
0x116959c82 <+194>: callq 0x11695c154 ; symbol stub for: free
0x116959c87 <+199>: movq 0x68(%rbx), %rdi
0x116959c8b <+203>: callq 0x11695b6c0 ; const_free
0x116959c90 <+208>: movq 0x70(%rbx), %rdi
0x116959c94 <+212>: callq 0x11695b6c0 ; const_free
0x116959c99 <+217>: movq 0x78(%rbx), %rdi
0x116959c9d <+221>: callq 0x11695b6c0 ; const_free
0x116959ca2 <+226>: movq %rbx, %rdi
0x116959ca5 <+229>: addq $0x8, %rsp
0x116959ca9 <+233>: popq %rbx
0x116959caa <+234>: popq %rbp
0x116959cab <+235>: jmp 0x11695c154 ; symbol stub for: free
0x116959cb0 <+240>: movq 0x78(%rbx), %rsi
0x116959cb4 <+244>: movq %rbx, %rdi
0x116959cb7 <+247>: xorl %eax, %eax
0x116959cb9 <+249>: callq 0x116959750 ; printOutput
0x116959cbe <+254>: leaq 0x285c(%rip), %rsi ; "\n\end{document}\n"
0x116959cc5 <+261>: movq %rbx, %rdi
0x116959cc8 <+264>: xorl %eax, %eax
0x116959cca <+266>: callq 0x116959750 ; printOutput
0x116959ccf <+271>: cmpl $0x1, 0x48(%rbx)
0x116959cd3 <+275>: jne 0x116959c3c ; <+124>
0x116959cd9 <+281>: movl 0x60(%rbx), %edx
0x116959cdc <+284>: leaq 0x284f(%rip), %rsi ; "%% Calculated string width %d times\n"
0x116959ce3 <+291>: movq %rbx, %rdi
0x116959ce6 <+294>: xorl %eax, %eax
0x116959ce8 <+296>: callq 0x116959750 ; printOutput
0x116959ced <+301>: cmpl $0x0, 0x80(%rbx)
0x116959cf4 <+308>: jne 0x116959c49 ; <+137>
0x116959cfa <+314>: movq (%rbx), %rdi
0x116959cfd <+317>: callq 0x11695c148 ; symbol stub for: fclose
0x116959d02 <+322>: movq $0x0, (%rbx)
0x116959d09 <+329>: jmp 0x116959c49 ; <+137>
0x116959d0e <+334>: nop
Er, miscounted the free()s, I think it's actually
free(tikzInfo->outColorFileName);
from https://github.com/daqana/tikzDevice/blob/master/src/tikzDevice.c#L701
It's possible the heap corruption is being caused by a different package (what I'm calling to generate bar
), though I can't say for sure since it's difficult to repro.
Please try to find a way to reproduce the issue. Looking at the code it seems that both tikzInfo->outColorFileName
and tikzInfo->originalColorFileName
are allocated when the colorFile
parameter is set. This happens by default, but maybe you are explicitly un-setting this argument?
I'm not doing anything to explicitly un-set colorFile. I'm pretty sure it's heap corruption because sometimes the pointer being freed has suspicious values like 0xf000000000000000
.
I've played around some more with a debugger attached and it looks like in the cases where the error is triggered, TikZ_Setup
is called but somehow TikZ_Open
is not. This would explain why outColorFileName
is uninitialized.
I'm not expert on the GraphicsDevice API, so I don't really know whether this is expected or not. But I think the error can be avoided by initializing the pointers in TikZ_Setup to NULL, then adding guards in TikZ_Close.
My repro code looks like:
tikz(
foo,
onefile = FALSE,
timestamp = FALSE
)
ThingThatGeneratesBar()
dev.off()
Note that it seems sensitive to seemingly innocuous changes (e.g. if I change ThingThatGeneratesBar()
to bar <- ThingThatGeneratesBar(); print(bar)
, I can't repro anymore). That could just be noise, but it's what makes me wonder about corruption since it smells like non-determinism.
Okay, consistent repro is:
create a file repro.R
with the contents:
library(tikzDevice)
tikz("deleteme", onefile = FALSE)
dev.off()
i.e. this opens a TikZ device, doesn't print anything to it, then closes it. Then call source("repro.R")
.