#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
int /*<<< orphan*/ free(size_t *);
size_t *malloc(int);
int /*<<< orphan*/ printf(char *);
void invalid_free_test1(void) {
  size_t *p = malloc(32);
  printf("testing invalid free\n");
  *(p) = *(p - (16 / sizeof(size_t)) - 2);
  *(p + 1) = ((*(p - (16 / sizeof(size_t)) - 1) & ~3) - (16 + 8)) |
             (*(p - (16 / sizeof(size_t)) - 1) & 3);
  free(p + 2);
}


x86 assembly (clang, -O0):
<invalid_free_test1>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
mov    $0x20,%edi
call   1050 <malloc@plt>
mov    %rax,-0x8(%rbp)
lea    0xeb3(%rip),%rdi
call   1040 <printf@plt>
mov    -0x8(%rbp),%rax
mov    -0x20(%rax),%rcx
mov    -0x8(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x8(%rbp),%rax
mov    -0x18(%rax),%rcx
and    $0xfffffffffffffffc,%rcx
sub    $0x18,%rcx
mov    -0x8(%rbp),%rax
mov    -0x18(%rax),%rax
and    $0x3,%rax
or     %rax,%rcx
mov    -0x8(%rbp),%rax
mov    %rcx,0x8(%rax)
mov    -0x8(%rbp),%rdi
add    $0x10,%rdi
call   1030 <free@plt>
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<invalid_free_test1>:
push   %rbx
mov    $0x20,%edi
call   1050 <malloc@plt>
mov    %rax,%rbx
lea    0xebb(%rip),%rdi
call   1040 <puts@plt>
mov    -0x20(%rbx),%rax
mov    -0x18(%rbx),%rcx
mov    %rax,(%rbx)
add    $0xffffffffffffffe8,%rcx
mov    %rcx,0x8(%rbx)
add    $0x10,%rbx
mov    %rbx,%rdi
pop    %rbx
jmp    1030 <free@plt>

LLVM IR (-O0):
@.str = [22 x i8] c"testing invalid free\0A\00"
define void @invalid_free_test1() {
%1 = alloca i64*
%2 = call i64* @malloc(i32 32)
store i64* %2, i64** %1
%3 = call i32 @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str, i64 0, i64 0))
%4 = load i64*, i64** %1
%5 = getelementptr inbounds i64, i64* %4, i64 -2
%6 = getelementptr inbounds i64, i64* %5, i64 -2
%7 = load i64, i64* %6
%8 = load i64*, i64** %1
store i64 %7, i64* %8
%9 = load i64*, i64** %1
%10 = getelementptr inbounds i64, i64* %9, i64 -2
%11 = getelementptr inbounds i64, i64* %10, i64 -1
%12 = load i64, i64* %11
%13 = and i64 %12, -4
%14 = sub i64 %13, 24
%15 = load i64*, i64** %1
%16 = getelementptr inbounds i64, i64* %15, i64 -2
%17 = getelementptr inbounds i64, i64* %16, i64 -1
%18 = load i64, i64* %17
%19 = and i64 %18, 3
%20 = or i64 %14, %19
%21 = load i64*, i64** %1
%22 = getelementptr inbounds i64, i64* %21, i64 1
store i64 %20, i64* %22
%23 = load i64*, i64** %1
%24 = getelementptr inbounds i64, i64* %23, i64 2
%25 = call i32 @free(i64* %24)
ret void
}

LLVM IR (-O2):
@str = [21 x i8] c"testing invalid free\00"
define void @invalid_free_test1() {
%1 = tail call i64* @malloc(i32 32)
%2 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([21 x i8], [21 x i8]* @str, i64 0, i64 0))
%3 = getelementptr inbounds i64, i64* %1, i64 -4
%4 = load i64, i64* %3
store i64 %4, i64* %1
%5 = getelementptr inbounds i64, i64* %1, i64 -3
%6 = load i64, i64* %5
%7 = add i64 %6, -24
%8 = getelementptr inbounds i64, i64* %1, i64 1
store i64 %7, i64* %8
%9 = getelementptr inbounds i64, i64* %1, i64 2
%10 = tail call i32 @free(i64* %9)
ret void
}