<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 --- - FreeBSD projects/clang380-import for TARGET_ARCH=powerpc : clang 3.8.0 sometimes mishandles va_list overflow_arg_area vs. reg_save_area"
href="https://llvm.org/bugs/show_bug.cgi?id=26605">26605</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>FreeBSD projects/clang380-import for TARGET_ARCH=powerpc : clang 3.8.0 sometimes mishandles va_list overflow_arg_area vs. reg_save_area
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>3.8
</td>
</tr>
<tr>
<th>Hardware</th>
<td>Other
</td>
</tr>
<tr>
<th>OS</th>
<td>FreeBSD
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</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>markmi@dsl-only.net
</td>
</tr>
<tr>
<th>CC</th>
<td>dgregor@apple.com, llvm-bugs@lists.llvm.org
</td>
</tr>
<tr>
<th>Classification</th>
<td>Unclassified
</td>
</tr></table>
<p>
<div>
<pre>In a projects/clang380-import context libxo code use by "ls -l -n /" gets a
segmentation violation (SEGV) for TARGET_ARCH=powerpc for
buildworld/installworld. The later simplified code reproduces the problem.
The issue is complicated alignment/placement handling of va_list content
between overflow_arg_area and reg_save_area that can happen when things larger
than 4 bytes in size are involved in the mix, such as intmax_t.
It can be that only 4 bytes are left in reg_save_area when the next things is,
say, 8 bytes in size. The next thing after that can be 4 bytes in size --which
place does the 4 byte item go and which is it extracted from?
The code generated is not consistent with itself. The following short program
demonstrates the problem.
#include <stdarg.h> // for va_list, va_start, va_arg, va_end
#include <stdint.h> // for intmax_t
intmax_t
va_test (char *s, ...)
{
va_list vap;
va_start(vap, s);
char* t0 = va_arg(vap, char*);
unsigned int o0 = va_arg(vap, unsigned int);
int c0 = va_arg(vap, int);
unsigned int u0 = va_arg(vap, unsigned int);
int c1 = va_arg(vap, int);
char * t1 = va_arg(vap, char*);
intmax_t j0 = va_arg(vap, intmax_t); // This spans into
overflow_arg_area.
int c2 = va_arg(vap, int); // A copy was put in the
// overflow_arg_area because of
the
// above.
// But this tries to extract from
the
// last 4 bytes of the
reg_save_area.
// It does not increment the
// overflow_arg_area position
pointer
// past the copy that is there.
char * t2 = va_arg(vap, char*); // The lack of increment before
makes
// this extraction off by 4 bytes.
char t2fc = *t2; // <<< This gets SEGV. t2 actually got what
should be
// the c2 value.
intmax_t j1 = va_arg(vap, intmax_t);
va_end(vap);
return (intmax_t) ((s-t2)+(t0-t1)+o0+u0+j0+j1+c0+c1+c2+t2fc);
// Avoid any optimize-away for lack of use.
}
int main(void)
{
char s[1025] = "test string for this";
char* t0 = s + 5;
unsigned int o0 = 3;
int c0 = 1;
unsigned int u0 = 1;
int c1 = 3;
char * t1 = s + 12;
intmax_t j0 = 314159265358979323;
int c2 = 4;
char * t2 = s + 16;
intmax_t j1 = ~314159265358979323;
intmax_t result = va_test(s,t0,o0,c0,u0,c1,t1,j0,c1,t2,j1);
return (int) (result - (intmax_t)
((s-t2)+(t0-t1)+o0+u0+j0+j1+c0+c1+c2+*t2));
// Avoid any optimize-away for lack of use.
}
Context:
# freebsd-version -ku; uname -aKU
11.0-CURRENT
11.0-CURRENT
FreeBSD FBSDG4C1 11.0-CURRENT FreeBSD 11.0-CURRENT #3 r295351M: Sat Feb 6
16:27:58 PST 2016
markmi@FreeBSDx64:/usr/obj/clang_gcc421/powerpc.powerpc/usr/src/sys/GENERICvtsc-NODEBUG
powerpc 1100097 1100097</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>