<html>
<head>
<base href="https://llvm.org/bugs/" />
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW --- - [windows/arm] extraneous C++ object destructor call added when objects are passed by value"
href="https://llvm.org/bugs/show_bug.cgi?id=29136">29136</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>[windows/arm] extraneous C++ object destructor call added when objects are passed by value
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>3.8
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Windows NT
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Keywords</th>
<td>miscompilation
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>C++
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>adrien@guinet.me
</td>
</tr>
<tr>
<th>CC</th>
<td>dgregor@apple.com, llvm-bugs@lists.llvm.org, szkudl.k@gmail.com
</td>
</tr>
<tr>
<th>Classification</th>
<td>Unclassified
</td>
</tr></table>
<p>
<div>
<pre>This is only happening when using Clang under Windows to generate Thumb code.
When a C++ object is passed by value to a function, the temporary object
created by copy is destructed twice, once in the callee function (which is
okay) and once more in the caller function (which should not happen). This
leads to a double free of a C++ object.
Attached is a minimal test case that reproduces the problem (double_free.cpp,
reduced by Kevin Szkudlapski in CC).
Here is the assembler output without any optimisation:
<span class="quote">> clang.exe double_free.cpp -c -o double_free.o --target=armv7-pc-windows-msvc -fmsc-version=1900 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1</span >
(using IDA)
; int __cdecl main(int argc, const char **argv, const char **envp)
EXPORT main
main
var_28 = -0x28
tmpObject = -0x24
var_20 = -0x20
var_1C = -0x1C
var_18 = -0x18
var_14 = -0x14
var_10 = -0x10
var_C = -0xC
PUSH.W {R11,LR}
MOV R11, SP
SUB SP, SP, #0x20
MOVS R0, #0
STR R0, [SP,#0x28+var_C]
ADD R1, SP, #0x28+var_10
STR R0, [SP,#0x28+var_18]
MOV R0, R1
STR R1, [SP,#0x28+var_1C]
BL c::c(void)
MOV R0, #`string' ; "f start"
BL puts
ADD R1, SP, #0x28+var_14
STR R0, [SP,#0x28+var_20]
MOV R0, R1
LDR.W LR, [SP,#0x28+var_1C]
STR R1, [SP,#0x28+tmpObject]
MOV R1, LR
BL c::c(c const &)
BL f(c)
LDR R0, [SP,#0x28+tmpObject]
BL c::~c(void) ; double free happens here!
MOV R0, #`string' ; "f end"
BL puts
LDR R1, [SP,#0x28+var_18]
STR R1, [SP,#0x28+var_C]
LDR.W LR, [SP,#0x28+var_1C]
STR R0, [SP,#0x28+var_28]
MOV R0, LR
BL c::~c(void)
LDR R0, [SP,#0x28+var_C]
ADD SP, SP, #0x20
POP.W {R11,PC}
And the "f::f" function:
void __cdecl f(class c)
var_10 = -0x10
var_C = -0xC
PUSH.W {R11,LR}
MOV R11, SP
SUB SP, SP, #8
MOV R0, #`string' ; "f inside"
BL puts
ADD.W LR, SP, #0x10+var_C
STR R0, [SP,#0x10+var_10]
MOV R0, LR
BL c::~c(void) ; this one is okay and destruct the temporary
object
ADD SP, SP, #8
POP.W {R11,PC}
The LLVM IR also reflects this issue. The optimized code (-O2) shows three
printf calls with "dtor: %p" as argument (where only two should be present, one
for the original copy and one for the temporary object).
This has been tested using the official clang 3.8.1 release (not the 3.9RC or
trunk).
Let us know if more information are needed!
Thanks!</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>