void foo (void) { char b[10]; __builtin_memmove (&a[0], &a[20], 20); __builtin_memmove (&b[1], &a[25], 9); bar (b); }
void foo (int *a, char *b, char *c) { /* One check for c[0], one check for a[], one check for c and 2 checks for b. */ __builtin_memmove (c, b, a[c[0]]); /* One check for a[], one check for c and one check for b. */ __builtin_memmove (c, b, a[b[0]]); /* For a total of 8 checks. */ }
void foo (int *a, char *b, char *c) { /* One check for c[0], one check for a[]. */ __builtin_memmove (c, b, a[c[0]]); /* One check for b[0], one check for a[]. */ __builtin_memmove (c, b, a[b[0]]); /* For a total of 4 checks. */ int d = c[0] == b[0]; }
int main () { // ***** main ***** char *pj, *pq, *pr; // buffer pointers: inp,out,/out char *jjj = malloc(JBFSIZE); // allocate input line buffer char *qqq = malloc(QBFSIZE); // output buffer (dyn. size) char *pqstop = qqq+QBFSIZE; // end-of-buffer pointer char xtab[256] = VALL; // char conversion table if (!jjj || !qqq) return errex("Buffer allocation", !jjj + !qqq); pj = fgets(jjj,JBFSIZE,stdin); // fetch 1st line if (!pj) return errex("No input data",0); if (*jjj != '>') return errex("1st char not '>'", 0); while (pj) { // MAIN LOOP: process data fputs(jjj, stdout); // output ID line for (pq=qqq+1, pr=pqstop; ; pq++) { // LOOP: fill output buffer pj = fgets(jjj, JBFSIZE, stdin); // get line from stdin if (!pj || (*jjj=='>')) break; // EOF or new ID line if (pr <= (pq+61)) { // need to resize buffer char *newstop = pqstop + 12777888; char *newptr = realloc(qqq, newstop-qqq); if (!newptr) return errex("Out of memory", 0); if (newptr != qqq) { // new base: adj. pointers size_t x = newptr-qqq; // offset for pointer update pq+=x; pr+=x; qqq+=x; newstop+=x; pqstop+=x; } pr = __builtin_memmove(newstop-(pqstop-pr), pr, pqstop-pr); pqstop = newstop; // buffer resize complete } while (*pj) { // LOOP: conv. & revert line char c = xtab[(unsigned char)(*pj++)]; if (c) // conversion valid *(--pr) = c; } } for (pq = qqq; pr<pqstop; ) { // LOOP: format output size_t x = (pqstop-pr)<60 ? pqstop-pr : 60; __builtin_memmove(pq,pr,x); // move line to free space pr+=x; pq+=x; *(pq++) = 0xA; // adjust pointers, add LF } fwrite(qqq, 1, pq-qqq, stdout); // output converted data } return 0; }
void foo (int *a, char *b, char *c) { /* One check for a[]. */ __builtin_memmove (c, b, a[0]); /* For a total of 1 checks. */ int d = a[0] == 0; }
static inline void foo (unsigned h, V j, U k, V n) { k /= h; __builtin_memmove (&h, &n, 1); n[j[1]] *= 0x7FFFFFFFFFFFFFFF; j[k[5]] = 0; g = n; i = h + j + n; }
int main(int argc, char **argv) { void *ptr; unsigned long dst; unsigned long src = ~0; ptr = __builtin_memmove(&dst, &src, sizeof(dst)); (void)ptr; return 0; }
void f(void *d, const void *s, __SIZE_TYPE__ n) { void *t1 = __builtin_memcpy (d, s, n); if (t1 == 0) __builtin_abort (); void *t2 = __builtin_memmove (d, s, n); if (t2 == 0) __builtin_abort (); void *t3 = __builtin_memset (d, 0, n); if (t3 == 0) __builtin_abort (); void *t4 = __builtin_strcpy (d, s); if (t4 == 0) __builtin_abort (); void *t5 = __builtin_strncpy (d, s, n); if (t5 == 0) __builtin_abort (); void *t6 = __builtin_strcat (d, s); if (t6 == 0) __builtin_abort (); void *t7 = __builtin_strncat (d, s, n); if (t7 == 0) __builtin_abort (); void *t8 = __builtin_stpcpy (d, s); if (t8 == 0) __builtin_abort (); void *t9 = __builtin_stpncpy (d, s, n); if (t9 == 0) __builtin_abort (); }
/* * Copyright (c) 2017, 2018, Oracle and/or its affiliates. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials provided * with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ int main() { unsigned int a = 0x11223344; unsigned int b = 0; __builtin_memmove(&a, &b, sizeof(a)); return a != b; }
void move(char *target, char *source, int length) { __builtin_memmove(target, source, length); }
static void __attribute__((constructor)) startup(void) { #else #define RETURN_VALUE 0 static void *ignore_ud2_addr; // scratch test code int main(void) { #endif char *debug_level_str = getenv("TRAP_SYSCALLS_DEBUG"); char *footprint_fd_str = getenv("TRAP_SYSCALLS_FOOTPRINT_FD"); char *trace_fd_str = getenv("TRAP_SYSCALLS_TRACE_FD"); char *sleep_for_seconds_str = getenv("TRAP_SYSCALLS_SLEEP_FOR_SECONDS"); char *stop_self_str = getenv("TRAP_SYSCALLS_STOP_SELF"); stop_self = (stop_self_str != NULL); footprints_spec_filename = getenv("TRAP_SYSCALLS_FOOTPRINT_SPEC_FILENAME"); struct timespec one_second = { /* seconds */ 1, /* nanoseconds */ 0 }; if (debug_level_str) debug_level = atoi(debug_level_str); if (trace_fd_str) trace_fd = atoi(trace_fd_str); if (footprint_fd_str) footprint_fd = atoi(footprint_fd_str); if (sleep_for_seconds_str) sleep_for_seconds = atoi(sleep_for_seconds_str); debug_printf(0, "Debug level is %s=%d.\n", debug_level_str, debug_level); if (stop_self) { self_pid = raw_getpid(); debug_printf(0, "TRAP_SYSCALLS_STOP_SELF is set, sending SIGSTOP to self (pid %d)\n", self_pid); raw_kill(self_pid, SIGSTOP); } debug_printf(0, "TRAP_SYSCALLS_SLEEP_FOR_SECONDS is %s, pausing for %d seconds", sleep_for_seconds_str, sleep_for_seconds); for (int i = 0; i < sleep_for_seconds; i++) { raw_nanosleep(&one_second, NULL); debug_printf(0, "."); } debug_printf(0, "\n"); /* Is fd open? If so, it's the input fd for our sanity check info * from systemtap. */ debug_printf(0, "TRAP_SYSCALLS_FOOTPRINT_FD is %s, ", footprint_fd_str); if (footprint_fd > 2) { struct stat buf; int stat_ret = raw_fstat(footprint_fd, &buf); if (stat_ret == 0) { debug_printf(0, "fd %d is open; outputting systemtap cross-check info.\n", footprint_fd); /* PROBLEM: ideally we'd read in the stap script's output ourselves, and process * it at every system call. But by reading in stuff from stap, we're doing more * copying to/from userspace, so creating a feedback loop which would blow up. * * Instead we write out what we think we touched, and do a diff outside the process. * This also adds noise to stap's output, but without the feedback cycle: we ourselves * won't read the extra output, hence won't write() more stuff in response. */ __write_footprints = 1; footprints_out = fdopen(footprint_fd, "a"); if (!footprints_out) { debug_printf(0, "Could not open footprints output stream for writing!\n"); } if (footprints_spec_filename) { footprints = parse_footprints_from_file(footprints_spec_filename, &footprints_env); } else { debug_printf(0, "no footprints spec filename provided\n", footprints_spec_filename); } } else { debug_printf(0, "fd %d is closed; skipping systemtap cross-check info.\n", footprint_fd); } } else { debug_printf(0, "skipping systemtap cross-check info\n"); } debug_printf(0, "TRAP_SYSCALLS_TRACE_FD is %s, ", trace_fd_str); if (!trace_fd_str || trace_fd == 2) { debug_printf(0, "dup'ing stderr, "); trace_fd = dup(2); } if (trace_fd >= 0) { struct stat buf; int stat_ret = raw_fstat(trace_fd, &buf); if (stat_ret == 0) { debug_printf(0, "fd %d is open; outputting traces there.\n", trace_fd); __write_traces = 1; traces_out = fdopen(trace_fd, "a"); if (!traces_out) { debug_printf(0, "Could not open traces output stream for writing!\n"); } } else { debug_printf(0, "fd %d is closed; not outputting traces.\n", trace_fd); } } else { debug_printf(0, "not outputting traces.\n"); } int fd = raw_open("/proc/self/maps", O_RDONLY); if (fd != -1) { // we use a simple buffer and a read loop char buf[8192]; unsigned int ret; char *buf_pos = &buf[0]; // the next position to fill in the buffer char *entry_start_pos = &buf[0]; // the position size_t size_requested; do { // read some stuff, perhaps filling up the buffer size_requested = sizeof buf - (buf_pos - buf); ret = raw_read(fd, buf_pos, size_requested); char *buf_limit = buf_pos + ret; assert(buf_limit <= &buf[sizeof buf]); // we have zero or more complete entries in the buffer; iterate over them char *seek_pos; while (1) { seek_pos = entry_start_pos; // search forward for a newline while (seek_pos != buf_limit && *seek_pos != '\n') { ++seek_pos; } // did we find one? if (seek_pos == buf_limit) { // no! // but we have a partial entry in the buffer // between entry_start_pos and seek_pos; // copy it to the start, re-set and continue __builtin_memmove(&buf[0], entry_start_pos, seek_pos - entry_start_pos); buf_pos = &buf[seek_pos - entry_start_pos]; entry_start_pos = &buf[0]; break; } else { assert(*seek_pos == '\n'); // we have a complete entry; read it and advance entry_start_pos char debug_buf1[seek_pos - entry_start_pos + 1]; strncpy(debug_buf1, entry_start_pos, seek_pos - entry_start_pos); debug_buf1[sizeof debug_buf1 - 1] = '\0'; debug_printf(1, "DEBUG: entry is: %s\n", debug_buf1); char debug_buf2[buf_pos - buf]; strncpy(debug_buf2, buf, buf_pos - buf); debug_buf2[sizeof debug_buf2 - 1] = '\0'; debug_printf(1, "DEBUG: buffer is: %s", debug_buf2); saw_mapping(entry_start_pos, seek_pos); entry_start_pos = seek_pos + 1; // if the newline was the last in the buffer, break and read more if (entry_start_pos == buf_pos + sizeof buf) { buf_pos = entry_start_pos = &buf[0]; break; } // else we might have another entry; go round again continue; } } } while (ret > 0); raw_close(fd); } /* Install our SIGILL (was SIGTRAP, but that interferes with gdb) handler. * Linux seems to require us to provide a restorer; the code is in restore_rt. */ struct sigaction action = { //.sa_sigaction = &handle_sigtrap, .sa_handler = &handle_sigill, .sa_mask = 0, .sa_flags = /*SA_SIGINFO |*/ 0x04000000u /* SA_RESTORER */ | /*SA_RESTART |*/ SA_NODEFER, .sa_restorer = restore_rt }; struct sigaction oldaction; raw_rt_sigaction(SIGILL, &action, &oldaction); /* Un-executablize our own code, except for the signal handler and the remainder of * this function and those afterwards. * * For this, we need our load address. How can we get this? We've already seen it! */ // long int len = &&exit_and_return - our_text_begin_address; // long int ret; // long int longprot = PROT_NONE; // long int op = SYS_mprotect; // __asm__ (".align 4096"); exit_and_return: //__asm__ volatile ("movq %0, %%rdi # \n\ // movq %1, %%rsi # \n\ // movq %2, %%rdx # \n\ // "FIX_STACK_ALIGNMENT " \n\ // movq %3, %%rax # \n\ // syscall # do the syscall \n\ // "UNFIX_STACK_ALIGNMENT " \n" // : /* no output*/ : "rm"(our_text_begin_address), "rm"(len), "rm"(longprot), "rm"(op) : "%rax", "r12", SYSCALL_CLOBBER_LIST); #ifdef EXECUTABLE // HACK for testing: do a ud2 right now! ignore_ud2_addr = &&ud2_addr; ud2_addr: __asm__ ("ud2\n"); // we must also exit without running any libdl exit handlers, // because we're an executable so our csu/startfiles include some cleanup // that will now cause traps (this isn't necessary in the shared library case) raw_exit(0); #endif return RETURN_VALUE; } // For debug printing inside handle_sigill we have to know // that it's our own debug printing in order to filter it // out of the footprints, hence this noinline function // rather than using the normal macro __attribute__ ((noinline)) static void _handle_sigill_debug_printf(int level, const char *fmt, ...) { va_list vl; va_start(vl, fmt); if ((level) <= debug_level) { vfprintf(*p_err_stream, fmt, vl); fflush(*p_err_stream); } va_end(vl); }
domem (void *dest, const void *src, int len) { __builtin_memmove (dest, src, len); }
static inline VOID EmulatorMoveMemory(OUT VOID UNALIGNED *Destination, IN const VOID UNALIGNED *Source, IN SIZE_T Length) { #if 1 /* * We use a switch here to detect small moves of memory, as these * constitute the bulk of our moves. * Using RtlMoveMemory for all these small moves would be slow otherwise. */ switch (Length) { case 0: return; case sizeof(UCHAR): *(PUCHAR)Destination = *(PUCHAR)Source; return; case sizeof(USHORT): *(PUSHORT)Destination = *(PUSHORT)Source; return; case sizeof(ULONG): *(PULONG)Destination = *(PULONG)Source; return; case sizeof(ULONGLONG): *(PULONGLONG)Destination = *(PULONGLONG)Source; return; default: #if defined(__GNUC__) __builtin_memmove(Destination, Source, Length); #else RtlMoveMemory(Destination, Source, Length); #endif } #else // defined(_MSC_VER) PUCHAR Dest = (PUCHAR)Destination; PUCHAR Src = (PUCHAR)Source; SIZE_T Count, NewSize = Length; /* Move dword */ Count = NewSize >> 2; // NewSize / sizeof(ULONG); NewSize = NewSize & 3; // NewSize % sizeof(ULONG); __movsd(Dest, Src, Count); Dest += Count << 2; // Count * sizeof(ULONG); Src += Count << 2; /* Move word */ Count = NewSize >> 1; // NewSize / sizeof(USHORT); NewSize = NewSize & 1; // NewSize % sizeof(USHORT); __movsw(Dest, Src, Count); Dest += Count << 1; // Count * sizeof(USHORT); Src += Count << 1; /* Move byte */ Count = NewSize; // NewSize / sizeof(UCHAR); // NewSize = NewSize; // NewSize % sizeof(UCHAR); __movsb(Dest, Src, Count); #endif }
void test_warn() { memset(&x1, 0, sizeof x1); // \ // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} memset(&x2, 0, sizeof x2); // \ // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} memmove(&x1, 0, sizeof x1); // \ // expected-warning{{destination for this 'memmove' call is a pointer to dynamic class 'struct X1'; vtable pointer will be overwritten}} \ // expected-note {{explicitly cast the pointer to silence this warning}} memmove(0, &x1, sizeof x1); // \ // expected-warning{{source of this 'memmove' call is a pointer to dynamic class 'struct X1'; vtable pointer will be moved}} \ // expected-note {{explicitly cast the pointer to silence this warning}} memcpy(&x1, 0, sizeof x1); // \ // expected-warning{{destination for this 'memcpy' call is a pointer to dynamic class 'struct X1'; vtable pointer will be overwritten}} \ // expected-note {{explicitly cast the pointer to silence this warning}} memcpy(0, &x1, sizeof x1); // \ // expected-warning{{source of this 'memcpy' call is a pointer to dynamic class 'struct X1'; vtable pointer will be copied}} \ // expected-note {{explicitly cast the pointer to silence this warning}} memcmp(&x1, 0, sizeof x1); // \ // expected-warning{{first operand of this 'memcmp' call is a pointer to dynamic class 'struct X1'; vtable pointer will be compared}} \ // expected-note {{explicitly cast the pointer to silence this warning}} memcmp(0, &x1, sizeof x1); // \ // expected-warning{{second operand of this 'memcmp' call is a pointer to dynamic class 'struct X1'; vtable pointer will be compared}} \ // expected-note {{explicitly cast the pointer to silence this warning}} __builtin_memset(&x1, 0, sizeof x1); // \ // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} __builtin_memset(&x2, 0, sizeof x2); // \ // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} __builtin_memmove(&x1, 0, sizeof x1); // \ // expected-warning{{destination for this '__builtin_memmove' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} __builtin_memmove(0, &x1, sizeof x1); // \ // expected-warning{{source of this '__builtin_memmove' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} __builtin_memcpy(&x1, 0, sizeof x1); // \ // expected-warning{{destination for this '__builtin_memcpy' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} __builtin_memcpy(0, &x1, sizeof x1); // \ // expected-warning{{source of this '__builtin_memcpy' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} __builtin___memset_chk(&x1, 0, sizeof x1, sizeof x1); // \ // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} __builtin___memset_chk(&x2, 0, sizeof x2, sizeof x2); // \ // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} __builtin___memmove_chk(&x1, 0, sizeof x1, sizeof x1); // \ // expected-warning{{destination for this '__builtin___memmove_chk' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} __builtin___memmove_chk(0, &x1, sizeof x1, sizeof x1); // \ // expected-warning{{source of this '__builtin___memmove_chk' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} __builtin___memcpy_chk(&x1, 0, sizeof x1, sizeof x1); // \ // expected-warning{{destination for this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} __builtin___memcpy_chk(0, &x1, sizeof x1, sizeof x1); // \ // expected-warning{{source of this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} }