Possible bug in latest version of clang on Mac OS X

Doug Simon doug.simon at oracle.com
Fri Mar 14 11:11:38 UTC 2014


(sending again with attachment inline)

Thanks to more investigation by Tom, it appears as though clang is legally omitting the null pointer check according to one way of interpreting (recent?) C++ specification around the value and type of NULL.

For anyone interested, I took some of Tom’s example code and made it into a standalone program (below) showing the issue:

$ clang++ -O3 -o clang_omits_null_check clang_omits_null_check.cpp 
$ ./clang_omits_null_check 
1. argc = 1 
2. argc = 1 
Illegal instruction: 4 

Switching to -O0 to prevents the crash: 

$ clang++ -O0 -o clang_omits_null_check clang_omits_null_check.cpp 
$ ./clang_omits_null_check 
1. argc = 1 
2. argc = 1 
3. argc = 1 

The only hints found on the web about this behavior so far are:

http://stackoverflow.com/questions/10153246/crashing-threads-with-intnull-1-problematic
http://blog.qt.digia.com/blog/2011/06/10/type-punning-and-strict-aliasing/


===== clang_omits_null_check.cpp ====

#include <stdio.h>
#include <stdint.h>

static char read1(char* handle, long offset) {
  char* obj = handle == NULL ? NULL : *(char**) handle;
  return *(char*)((intptr_t)obj + offset);
}

static char read2(char* handle, long offset) {
  char* obj = handle == NULL ? NULL : *(char**) handle;
  // Without the cast to intptr_t, this crashes since
  // the compiler dereferences handle first and then
  // adds offset to it.
  return *(char*)(          obj + offset);
}

int main(int argc, char** argv) {
  int* argcAddr = &argc;
  printf("1. argc = %d\n", argc);
  printf("2. argc = %d\n", read1(NULL, (long) argcAddr));
  printf("3. argc = %d\n", read2(NULL, (long) argcAddr));
}

=====================================


-Doug



On Mar 12, 2014, at 2:30 AM, Christian Thalinger <christian.thalinger at oracle.com> wrote:

> 
> On Mar 11, 2014, at 4:01 PM, Tom Rodriguez <tom.rodriguez at oracle.com> wrote:
> 
>> So this is a known clang/llvm issue?  Has it been reported?
> 
> I don’t think so.  At least I didn’t do it.
> 
>> 
>> tom
>> 
>> On Mar 11, 2014, at 3:14 PM, Christian Thalinger <christian.thalinger at oracle.com> wrote:
>> 
>>> Sigh.  Meta-circular FTW! ;-)
>>> 
>>> Did you add a new section like this:
>>> 
>>> # Clang 5.0
>>> ifeq ($(shell expr $(CC_VER_MAJOR) = 5 \& $(CC_VER_MINOR) = 0), 1)
>>> OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
>>> OPT_CFLAGS/unsafe.o += -O1
>>> OPT_CFLAGS/graalCompilerToVM.o += -O1
>>> endif
>>> 
>>> for 5.1 in make/bsd/makefiles/gcc.make?
>>> 
>>> On Mar 11, 2014, at 3:03 PM, Doug Simon <doug.simon at oracle.com> wrote:
>>> 
>>>> Since I have automatic updating enabled on my Mac, I was recently updated to the latest version of Xcode (5.1). I have just done my first recompile of HotSpot since this update and am seeing that clang appears to have a rather serious bug. In both disassembled functions below, the third parameter (%rdx) is a jobject that should be resolved via JNIHandles::resolve and then dereferenced *after* adding the fourth parameter (%rcx) to it. clang is inlining the call to JNIHandles::resolve but omitting the null check on the jobject value.
>>>> 
>>>> If this is really a bug, I’m sure reports about it will start showing up soon. In the meantime, don’t update Xcode.
>>>> 
>>>> -Doug
>>>> 
>>>> 
>>>> _Unsafe_GetLong:
>>>> 0000000000357e59	pushq	%rbp
>>>> 0000000000357e5a	movq	%rsp, %rbp
>>>> 0000000000357e5d	pushq	%r15
>>>> 0000000000357e5f	pushq	%r14
>>>> 0000000000357e61	pushq	%r12
>>>> 0000000000357e63	pushq	%rbx
>>>> 0000000000357e64	subq	$0x10, %rsp
>>>> 0000000000357e68	movq	%rcx, %r14
>>>> 0000000000357e6b	movq	%rdx, %r15
>>>> 0000000000357e6e	movq	%rdi, %rbx
>>>> 0000000000357e71	movl	0x90(%rbx), %eax
>>>> 0000000000357e77	addq	$-0x1f0, %rbx
>>>> 0000000000357e7e	cmpl	$0xdeab, %eax
>>>> 0000000000357e83	je	0x357e9c
>>>> 0000000000357e85	movl	0x280(%rbx), %eax
>>>> 0000000000357e8b	cmpl	$0xdeac, %eax
>>>> 0000000000357e90	je	0x357e9c
>>>> 0000000000357e92	movq	%rbx, %rdi
>>>> 0000000000357e95	callq	__ZN10JavaThread18block_if_vm_exitedEv
>>>> 0000000000357e9a	xorl	%ebx, %ebx
>>>> 0000000000357e9c	leaq	-0x28(%rbp), %r12
>>>> 0000000000357ea0	movq	%r12, %rdi
>>>> 0000000000357ea3	movq	%rbx, %rsi
>>>> 0000000000357ea6	callq	__ZN20ThreadInVMfromNativeC1EP10JavaThread
>>>> 0000000000357eab	movq	%rbx, -0x30(%rbp)
>>>> 0000000000357eaf	movq	(%r15), %rax
>>>> 0000000000357eb2	movq	(%rax,%r14), %rbx
>>>> 0000000000357eb6	leaq	-0x30(%rbp), %rdi
>>>> 0000000000357eba	callq	__ZN17HandleMarkCleanerD1Ev
>>>> 0000000000357ebf	movq	%r12, %rdi
>>>> 0000000000357ec2	callq	__ZN20ThreadInVMfromNativeD1Ev
>>>> 0000000000357ec7	movq	%rbx, %rax
>>>> 0000000000357eca	addq	$0x10, %rsp
>>>> 0000000000357ece	popq	%rbx
>>>> 0000000000357ecf	popq	%r12
>>>> 0000000000357ed1	popq	%r14
>>>> 0000000000357ed3	popq	%r15
>>>> 0000000000357ed5	popq	%rbp
>>>> 0000000000357ed6	ret
>>>> 
>>>> __Z33c2v_readUnsafeUncompressedPointerP7JNIEnv_P8_jobjectS2_l:
>>>> 000000000016e261	pushq	%rbp
>>>> 000000000016e262	movq	%rsp, %rbp
>>>> 000000000016e265	pushq	%r15
>>>> 000000000016e267	pushq	%r14
>>>> 000000000016e269	pushq	%r12
>>>> 000000000016e26b	pushq	%rbx
>>>> 000000000016e26c	subq	$0x10, %rsp
>>>> 000000000016e270	movq	%rcx, %r14
>>>> 000000000016e273	movq	%rdx, %r15
>>>> 000000000016e276	leaq	_TraceGraal(%rip), %rax
>>>> 000000000016e27d	cmpq	$0x3, (%rax)
>>>> 000000000016e281	jl	0x16e2ac
>>>> 000000000016e283	leaq	_tty(%rip), %rbx
>>>> 000000000016e28a	movq	(%rbx), %rdi
>>>> 000000000016e28d	leaq	0x23de25(%rip), %rsi ## literal pool for: "      TraceGraal-3: "
>>>> 000000000016e294	xorl	%eax, %eax
>>>> 000000000016e296	callq	__ZN12outputStream5printEPKcz
>>>> 000000000016e29b	movq	(%rbx), %rdi
>>>> 000000000016e29e	leaq	0x23ef0f(%rip), %rsi ## literal pool for: "CompilerToVM::readUnsafeUncompressedPointer"
>>>> 000000000016e2a5	xorl	%eax, %eax
>>>> 000000000016e2a7	callq	__ZN12outputStream8print_crEPKcz
>>>> 000000000016e2ac	leaq	__ZN18ThreadLocalStorage13_thread_indexE(%rip), %rax
>>>> 000000000016e2b3	movslq	(%rax), %rdi
>>>> 000000000016e2b6	callq	0x38a758 ## symbol stub for: _pthread_getspecific
>>>> 000000000016e2bb	movq	%rax, %rbx
>>>> 000000000016e2be	leaq	-0x28(%rbp), %r12
>>>> 000000000016e2c2	movq	%r12, %rdi
>>>> 000000000016e2c5	movq	%rbx, %rsi
>>>> 000000000016e2c8	callq	__ZN20ThreadInVMfromNativeC1EP10JavaThread
>>>> 000000000016e2cd	movq	%rbx, -0x30(%rbp)
>>>> 000000000016e2d1	movq	(%r15), %rax
>>>> 000000000016e2d4	movq	(%rax,%r14), %rdi
>>>> 000000000016e2d8	callq	__ZN10JNIHandles10make_localEP7oopDesc
>>>> 000000000016e2dd	movq	%rax, %rbx
>>>> 000000000016e2e0	leaq	-0x30(%rbp), %rdi
>>>> 000000000016e2e4	callq	__ZN17HandleMarkCleanerD1Ev
>>>> 000000000016e2e9	movq	%r12, %rdi
>>>> 000000000016e2ec	callq	__ZN20ThreadInVMfromNativeD1Ev
>>>> 000000000016e2f1	movq	%rbx, %rax
>>>> 000000000016e2f4	addq	$0x10, %rsp
>>>> 000000000016e2f8	popq	%rbx
>>>> 000000000016e2f9	popq	%r12
>>>> 000000000016e2fb	popq	%r14
>>>> 000000000016e2fd	popq	%r15
>>>> 000000000016e2ff	popq	%rbp
>>>> 000000000016e300	ret
>>>> 
>>>> 
>>> 
>> 
> 



More information about the graal-dev mailing list