#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 */
typedef scalar_t__ uid_t;
typedef scalar_t__ gid_t;

/* Variables and functions */
scalar_t__ getegid();
scalar_t__ geteuid();
scalar_t__ getgid();
scalar_t__ getuid();
int setegid(scalar_t__);
int seteuid(scalar_t__);
int setgroups(int, scalar_t__ *);
int setregid(scalar_t__, scalar_t__);
int setreuid(scalar_t__, scalar_t__);
int drop_privileges(uid_t uid, gid_t gid) {
  uid_t current_uid = getuid();
  gid_t current_gid = getgid();
  if (setgroups(1, &gid) == -1) {
    return 0;
  }
  if (gid != current_gid) {
    if (setregid(gid, gid) == -1) {
      return 0;
    }
  }
  if (uid != current_uid) {
    if (setreuid(uid, uid) == -1) {
      return 0;
    };
  }
  if (gid != current_gid && (setegid(current_gid) != -1 || getegid() != gid)) {
    return 0;
  }
  if (uid != current_uid && (seteuid(current_uid) != -1 || geteuid() != uid)) {
    return 0;
  }
  return 1;
}


x86 assembly (clang, -O0):
<drop_privileges>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    $0x0,%al
call   1030 <getuid@plt>
mov    %rax,-0x20(%rbp)
mov    $0x0,%al
call   1060 <getgid@plt>
mov    %rax,-0x28(%rbp)
mov    $0x1,%edi
lea    -0x18(%rbp),%rsi
call   1050 <setgroups@plt>
cmp    $0xffffffff,%eax
jne    11d9 <drop_privileges+0x49>
movl   $0x0,-0x4(%rbp)
jmp    12c4 <drop_privileges+0x134>
mov    -0x18(%rbp),%rax
cmp    -0x28(%rbp),%rax
je     120e <drop_privileges+0x7e>
mov    -0x18(%rbp),%rdi
mov    -0x18(%rbp),%rsi
call   1090 <setregid@plt>
cmp    $0xffffffff,%eax
jne    1209 <drop_privileges+0x79>
movl   $0x0,-0x4(%rbp)
jmp    12c4 <drop_privileges+0x134>
jmp    120e <drop_privileges+0x7e>
mov    -0x10(%rbp),%rax
cmp    -0x20(%rbp),%rax
je     1243 <drop_privileges+0xb3>
mov    -0x10(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1080 <setreuid@plt>
cmp    $0xffffffff,%eax
jne    123e <drop_privileges+0xae>
movl   $0x0,-0x4(%rbp)
jmp    12c4 <drop_privileges+0x134>
jmp    1243 <drop_privileges+0xb3>
mov    -0x18(%rbp),%rax
cmp    -0x28(%rbp),%rax
je     1280 <drop_privileges+0xf0>
mov    -0x28(%rbp),%rdi
call   10a0 <setegid@plt>
cmp    $0xffffffff,%eax
jne    1274 <drop_privileges+0xe4>
mov    $0x0,%al
call   1070 <getegid@plt>
cmp    -0x18(%rbp),%rax
je     1280 <drop_privileges+0xf0>
movl   $0x0,-0x4(%rbp)
jmp    12c4 <drop_privileges+0x134>
mov    -0x10(%rbp),%rax
cmp    -0x20(%rbp),%rax
je     12bd <drop_privileges+0x12d>
mov    -0x20(%rbp),%rdi
call   10b0 <seteuid@plt>
cmp    $0xffffffff,%eax
jne    12b1 <drop_privileges+0x121>
mov    $0x0,%al
call   1040 <geteuid@plt>
cmp    -0x10(%rbp),%rax
je     12bd <drop_privileges+0x12d>
movl   $0x0,-0x4(%rbp)
jmp    12c4 <drop_privileges+0x134>
movl   $0x1,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<drop_privileges>:
push   %rbp
push   %r15
push   %r14
push   %rbx
push   %rax
mov    %rdi,%r14
mov    %rsi,(%rsp)
xor    %ebp,%ebp
xor    %eax,%eax
call   1030 <getuid@plt>
mov    %rax,%r15
xor    %eax,%eax
call   1060 <getgid@plt>
mov    %rax,%rbx
mov    %rsp,%rsi
mov    $0x1,%edi
call   1050 <setgroups@plt>
cmp    $0xffffffff,%eax
je     1241 <drop_privileges+0xb1>
mov    (%rsp),%rdi
cmp    %rbx,%rdi
je     11dc <drop_privileges+0x4c>
mov    %rdi,%rsi
call   1090 <setregid@plt>
cmp    $0xffffffff,%eax
je     1241 <drop_privileges+0xb1>
cmp    %r14,%r15
je     11f1 <drop_privileges+0x61>
mov    %r14,%rdi
mov    %r14,%rsi
call   1080 <setreuid@plt>
cmp    $0xffffffff,%eax
je     1241 <drop_privileges+0xb1>
cmp    %rbx,(%rsp)
jne    1203 <drop_privileges+0x73>
cmp    %r14,%r15
jne    1221 <drop_privileges+0x91>
mov    $0x1,%ebp
jmp    1241 <drop_privileges+0xb1>
mov    %rbx,%rdi
call   10a0 <setegid@plt>
cmp    $0xffffffff,%eax
jne    1241 <drop_privileges+0xb1>
xor    %ebp,%ebp
xor    %eax,%eax
call   1070 <getegid@plt>
cmp    (%rsp),%rax
je     11f7 <drop_privileges+0x67>
jmp    1241 <drop_privileges+0xb1>
mov    %r15,%rdi
call   10b0 <seteuid@plt>
mov    $0x0,%ebp
cmp    $0xffffffff,%eax
jne    1241 <drop_privileges+0xb1>
xor    %ebp,%ebp
xor    %eax,%eax
call   1040 <geteuid@plt>
cmp    %r14,%rax
je     11fc <drop_privileges+0x6c>
mov    %ebp,%eax
add    $0x8,%rsp
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define i32 @drop_privileges(i64 %0, i64 %1) {
%3 = alloca i32
%4 = alloca i64
%5 = alloca i64
%6 = alloca i64
%7 = alloca i64
store i64 %0, i64* %4
store i64 %1, i64* %5
%8 = call i64 (...) @getuid()
store i64 %8, i64* %6
%9 = call i64 (...) @getgid()
store i64 %9, i64* %7
%10 = call i32 @setgroups(i32 1, i64* %5)
%11 = icmp eq i32 %10, -1
br i1 %11, label %12, label %13
12: ; preds = %2
store i32 0, i32* %3
br label %62
13: ; preds = %2
%14 = load i64, i64* %5
%15 = load i64, i64* %7
%16 = icmp ne i64 %14, %15
br i1 %16, label %17, label %24
17: ; preds = %13
%18 = load i64, i64* %5
%19 = load i64, i64* %5
%20 = call i32 @setregid(i64 %18, i64 %19)
%21 = icmp eq i32 %20, -1
br i1 %21, label %22, label %23
22: ; preds = %17
store i32 0, i32* %3
br label %62
23: ; preds = %17
br label %24
24: ; preds = %23, %13
%25 = load i64, i64* %4
%26 = load i64, i64* %6
%27 = icmp ne i64 %25, %26
br i1 %27, label %28, label %35
28: ; preds = %24
%29 = load i64, i64* %4
%30 = load i64, i64* %4
%31 = call i32 @setreuid(i64 %29, i64 %30)
%32 = icmp eq i32 %31, -1
br i1 %32, label %33, label %34
33: ; preds = %28
store i32 0, i32* %3
br label %62
34: ; preds = %28
br label %35
35: ; preds = %34, %24
%36 = load i64, i64* %5
%37 = load i64, i64* %7
%38 = icmp ne i64 %36, %37
br i1 %38, label %39, label %48
39: ; preds = %35
%40 = load i64, i64* %7
%41 = call i32 @setegid(i64 %40)
%42 = icmp ne i32 %41, -1
br i1 %42, label %47, label %43
43: ; preds = %39
%44 = call i64 (...) @getegid()
%45 = load i64, i64* %5
%46 = icmp ne i64 %44, %45
br i1 %46, label %47, label %48
47: ; preds = %43, %39
store i32 0, i32* %3
br label %62
48: ; preds = %43, %35
%49 = load i64, i64* %4
%50 = load i64, i64* %6
%51 = icmp ne i64 %49, %50
br i1 %51, label %52, label %61
52: ; preds = %48
%53 = load i64, i64* %6
%54 = call i32 @seteuid(i64 %53)
%55 = icmp ne i32 %54, -1
br i1 %55, label %60, label %56
56: ; preds = %52
%57 = call i64 (...) @geteuid()
%58 = load i64, i64* %4
%59 = icmp ne i64 %57, %58
br i1 %59, label %60, label %61
60: ; preds = %56, %52
store i32 0, i32* %3
br label %62
61: ; preds = %56, %48
store i32 1, i32* %3
br label %62
62: ; preds = %61, %60, %47, %33, %22, %12
%63 = load i32, i32* %3
ret i32 %63
}

LLVM IR (-O2):
define i32 @drop_privileges(i64 %0, i64 %1) {
%3 = alloca i64
store i64 %1, i64* %3
%4 = tail call i64 (...) @getuid()
%5 = tail call i64 (...) @getgid()
%6 = call i32 @setgroups(i32 1, i64* %3)
%7 = icmp eq i32 %6, -1
br i1 %7, label %37, label %8
8: ; preds = %2
%9 = load i64, i64* %3
%10 = icmp eq i64 %9, %5
br i1 %10, label %14, label %11
11: ; preds = %8
%12 = call i32 @setregid(i64 %9, i64 %9)
%13 = icmp eq i32 %12, -1
br i1 %13, label %37, label %14
14: ; preds = %11, %8
%15 = icmp eq i64 %4, %0
br i1 %15, label %19, label %16
16: ; preds = %14
%17 = call i32 @setreuid(i64 %0, i64 %0)
%18 = icmp eq i32 %17, -1
br i1 %18, label %37, label %19
19: ; preds = %16, %14
%20 = load i64, i64* %3
%21 = icmp eq i64 %20, %5
br i1 %21, label %29, label %22
22: ; preds = %19
%23 = call i32 @setegid(i64 %5)
%24 = icmp eq i32 %23, -1
br i1 %24, label %25, label %37
25: ; preds = %22
%26 = call i64 (...) @getegid()
%27 = load i64, i64* %3
%28 = icmp eq i64 %26, %27
br i1 %28, label %29, label %37
29: ; preds = %25, %19
br i1 %15, label %36, label %30
30: ; preds = %29
%31 = call i32 @seteuid(i64 %4)
%32 = icmp eq i32 %31, -1
br i1 %32, label %33, label %37
33: ; preds = %30
%34 = call i64 (...) @geteuid()
%35 = icmp eq i64 %34, %0
br i1 %35, label %36, label %37
36: ; preds = %33, %29
br label %37
37: ; preds = %30, %33, %22, %25, %16, %11, %2, %36
%38 = phi i32 [ 1, %36 ], [ 0, %2 ], [ 0, %11 ], [ 0, %16 ], [ 0, %25 ], [ 0, %22 ], [ 0, %33 ], [ 0, %30 ]
ret i32 %38
}