Example: pointer_copy_user_dataflow_direct_bytewise.c

#include <stdio.h>
#include <string.h>
int x=1;
void user_memcpy(unsigned char* dest,
unsigned char *src, size_t n) {
while (n > 0) {
*dest = *src;
src += 1;
dest += 1;
n -= 1;
}
}
int main() {
int *p = &x;
int *q;
user_memcpy((unsigned char*)&q,
(unsigned char*)&p, sizeof(int *));
*q = 11; // is this free of undefined behaviour?
printf("*p=%d *q=%d\n",*p,*q);
}
[link to test in Cerberus and Compiler Explorer]

Experimental data (what does this mean?)

gcc-8.1-O0 *p=11 *q=11
gcc-8.1-O2 *p=11 *q=11
gcc-8.1-O3 *p=11 *q=11
gcc-8.1-O2-no-strict-aliasing *p=11 *q=11
gcc-8.1-O3-no-strict-aliasing *p=11 *q=11
clang-6.0-O0 *p=11 *q=11
clang-6.0-O2 *p=11 *q=11
clang-6.0-O3 *p=11 *q=11
clang-6.0-O2-no-strict-aliasing *p=11 *q=11
clang-6.0-O3-no-strict-aliasing *p=11 *q=11
clang-6.0-UBSAN *p=11 *q=11
clang-6.0-ASAN *p=11 *q=11
clang-6.0-MSAN *p=11 *q=11
icc-19-O0 *p=11 *q=11
icc-19-O2 *p=11 *q=11
icc-19-O3 *p=11 *q=11
icc-19-O2-no-strict-aliasing *p=11 *q=11
icc-19-O3-no-strict-aliasing *p=11 *q=11
cerberus-concrete BEGIN EXEC[0]
Defined {value: "Specified(0)", stdout: "*p=11 *q=11\n", blocked: "false"}
END EXEC[0]
Time spent: 0.042101 seconds
cerberus-symbolic exit codes: compile 0 / execute 1 cerberus: internal error, uncaught exception:
Failure("TODO: Symbolic defacto, isWellAligned_ptrval")

gcc-4.9-shadowprov *p=11 *q=11
CHERI:MIPS-O0 *p=11 *q=11
CHERI:MIPS-O2 *p=11 *q=11
CHERI:MIPS-O2-no-strict-aliasing *p=11 *q=11
CHERI:CHERI-O0-uintcap-addr-exact-equals exit codes: compile 0 / execute -1 Terminated with signal 34: In-address space security exception
CHERI:CHERI-O2-uintcap-addr-exact-equals exit codes: compile 0 / execute -1 Terminated with signal 34: In-address space security exception
CHERI:CHERI-O2-no-strict-aliasing-uintcap-addr-exact-equals exit codes: compile 0 / execute -1 Terminated with signal 34: In-address space security exception
CHERI:CHERI-O0-uintcap-offset-exact-equals exit codes: compile 0 / execute -1 Terminated with signal 34: In-address space security exception
CHERI:CHERI-O2-uintcap-offset-exact-equals exit codes: compile 0 / execute -1 Terminated with signal 34: In-address space security exception
CHERI:CHERI-O2-no-strict-aliasing-uintcap-offset-exact-equals exit codes: compile 0 / execute -1 Terminated with signal 34: In-address space security exception
CHERI:CHERI-O0-uintcap-addr exit codes: compile 0 / execute -1 Terminated with signal 34: In-address space security exception
CHERI:CHERI-O2-uintcap-addr exit codes: compile 0 / execute -1 Terminated with signal 34: In-address space security exception
CHERI:CHERI-O2-no-strict-aliasing-uintcap-addr exit codes: compile 0 / execute -1 Terminated with signal 34: In-address space security exception
CHERI:CHERI-O0-uintcap-offset exit codes: compile 0 / execute -1 Terminated with signal 34: In-address space security exception
CHERI:CHERI-O2-uintcap-offset exit codes: compile 0 / execute -1 Terminated with signal 34: In-address space security exception
CHERI:CHERI-O2-no-strict-aliasing-uintcap-offset exit codes: compile 0 / execute -1 Terminated with signal 34: In-address space security exception
RV-Match *p=11 *q=11
ch2o *p=11 *q=11
compcert-3.2 *p=11 *q=11
compcert-3.2-O *p=11 *q=11
compcert-3.2-interp Time 0: calling main()
--[step_internal_function]-->
Time 1: in function main, statement
p = &x;
user_memcpy((unsigned char *) &q, (unsigned char *) &p, sizeof(int *));
*q = 11;
printf(__stringlit_1, *p, *q);
return 0;
--[step_seq]-->
Time 2: in function main, statement
p = &x;
user_memcpy((unsigned char *) &q, (unsigned char *) &p, sizeof(int *));
*q = 11;
printf(__stringlit_1, *p, *q);
--[step_seq]-->
Time 3: in function main, statement p = &x;
--[step_do_1]-->
Time 4: in function main, expression p = &x
--[red_var_local]-->
Time 5: in function main, expression <loc p> = &x
--[red_var_global]-->
Time 6: in function main, expression <loc p> = &<loc x>
--[red_addrof]-->
Time 7: in function main, expression <loc p> = <ptr x>
--[red_assign]-->
Time 8: in function main, expression <ptr x>
--[step_do_2]-->
Time 9: in function main, statement /*skip*/;
--[step_skip_seq]-->
Time 10: in function main, statement
user_memcpy((unsigned char *) &q, (unsigned char *) &p, sizeof(int *));
*q = 11;
printf(__stringlit_1, *p, *q);
--[step_seq]-->
Time 11: in function main, statement
user_memcpy((unsigned char *) &q, (unsigned char *) &p, sizeof(int *));
--[step_do_1]-->
Time 12: in function main, expression
user_memcpy((unsigned char *) &q, (unsigned char *) &p, sizeof(int *))
--[red_var_global]-->
Time 13: in function main, expression
<loc user_memcpy>((unsigned char *) &q,
(unsigned char *) &p,
sizeof(int *))
--[red_rvalof]-->
Time 14: in function main, expression
<ptr user_memcpy>((unsigned char *) &q,
(unsigned char *) &p,
sizeof(int *))
--[red_var_local]-->
Time 15: in function main, expression
<ptr user_memcpy>((unsigned char *) &<loc q>,
(unsigned char *) &p,
sizeof(int *))
--[red_addrof]-->
Time 16: in function main, expression
<ptr user_memcpy>((unsigned char *) <ptr q>,
(unsigned char *) &p,
sizeof(int *))
--[red_cast]-->
Time 17: in function main, expression
<ptr user_memcpy>(<ptr q>, (unsigned char *) &p, sizeof(int *))
--[red_var_local]-->
Time 18: in function main, expression
<ptr user_memcpy>(<ptr q>, (unsigned char *) &<loc p>, sizeof(int *))
--[red_addrof]-->
Time 19: in function main, expression
<ptr user_memcpy>(<ptr q>, (unsigned char *) <ptr p>, sizeof(int *))
--[red_cast]-->
Time 20: in function main, expression
<ptr user_memcpy>(<ptr q>, <ptr p>, sizeof(int *))
--[red_sizeof]-->
Time 21: in function main, expression <ptr user_memcpy>(<ptr q>, <ptr p>, 4U)
--[red_call]-->
Time 22: calling user_memcpy(<ptr>, <ptr>, 4)
--[step_internal_function]-->
Time 23: in function user_memcpy, statement
while (n > 0) {
*dest = *src;
src += 1;
dest += 1;
n -= 1;
}
--[step_while]-->
Time 24: in function user_memcpy, expression n > 0
--[red_var_local]-->
Time 25: in function user_memcpy, expression <loc n> > 0
--[red_rvalof]-->
Time 26: in function user_memcpy, expression 4U > 0
--[red_binop]-->
Time 27: in function user_memcpy, expression 1
--[step_while_true]-->
Time 28: in function user_memcpy, statement
*dest = *src; src += 1; dest += 1; n -= 1;
--[step_seq]-->
Time 29: in function user_memcpy, statement *dest = *src;
--[step_do_1]-->
Time 30: in function user_memcpy, expression *dest = *src
--[red_var_local]-->
Time 31: in function user_memcpy, expression *<loc dest> = *src
--[red_rvalof]-->
Time 32: in function user_memcpy, expression *<ptr> = *src
--[red_deref]-->
Time 33: in function user_memcpy, expression <loc> = *src
--[red_var_local]-->
Time 34: in function user_memcpy, expression <loc> = *<loc src>
--[red_rvalof]-->
Time 35: in function user_memcpy, expression <loc> = *<ptr>
--[red_deref]-->
Time 36: in function user_memcpy, expression <loc> = <loc>
--[red_rvalof]-->
Time 37: in function user_memcpy, expression <loc> = <undef>
Stuck state: in function user_memcpy, expression <loc> = <undef>
Stuck subexpression: <loc> = <undef>
ERROR: Undefined behavior
In file included from pointer_copy_user_dataflow_direct_bytewise.c:1:
In file included from /usr/include/stdio.h:64:
In file included from /usr/include/_stdio.h:68:
/usr/include/sys/cdefs.h:81:2: warning: "Unsupported compiler detected" [-W#warnings]
#warning "Unsupported compiler detected"
^
1 warning generated.