diff --git a/src/string/Cargo.toml b/src/string/Cargo.toml
index d00a3e5c11839ef8c485e9612172252cd0992c63..771d72c5ce3b1405fa48cdaf3f4e867b61fd092c 100644
--- a/src/string/Cargo.toml
+++ b/src/string/Cargo.toml
@@ -10,4 +10,5 @@ cbindgen = { path = "../../cbindgen" }
 [dependencies]
 platform = { path = "../platform" }
 stdlib = { path = "../stdlib" }
-errno = { path = "../errno" }
\ No newline at end of file
+errno = { path = "../errno" }
+compiler_builtins = { git = "https://github.com/rust-lang-nursery/compiler-builtins.git", default-features = false, features = ["mem"] }
diff --git a/src/string/src/lib.rs b/src/string/src/lib.rs
index c7178b5c3c160d755444b5cb5433ed1a7faa8dae..a3d454fe7efd5765d9e90e6c93496cd9c5c2477c 100644
--- a/src/string/src/lib.rs
+++ b/src/string/src/lib.rs
@@ -1,7 +1,9 @@
 //! string implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/string.h.html
 
+#![feature(compiler_builtins_lib)]
 #![no_std]
 
+extern crate compiler_builtins;
 extern crate errno;
 extern crate platform;
 extern crate stdlib;
@@ -10,15 +12,40 @@ use platform::types::*;
 use errno::*;
 use core::cmp;
 use core::usize;
+use core::ptr;
 
 #[no_mangle]
-pub extern "C" fn memccpy(s1: *mut c_void, s2: *const c_void, c: c_int, n: usize) -> *mut c_void {
-    unimplemented!();
+pub unsafe extern "C" fn memccpy(
+    dest: *mut c_void,
+    src: *const c_void,
+    c: c_int,
+    n: usize,
+) -> *mut c_void {
+    use compiler_builtins::mem::memcpy;
+    let dest = dest as *mut u8;
+    let to = memchr(src, c, n);
+    if to.is_null() {
+        return to;
+    }
+    let src = src as *mut u8;
+    let dist = (to as usize) - (src as usize);
+    if memcpy(dest, src, dist).is_null() {
+        return ptr::null_mut();
+    }
+    dest.offset(dist as isize + 1) as *mut c_void
 }
 
 #[no_mangle]
-pub extern "C" fn memchr(s: *const c_void, c: c_int, n: usize) -> *mut c_void {
-    unimplemented!();
+pub unsafe extern "C" fn memchr(s: *const c_void, c: c_int, n: usize) -> *mut c_void {
+    let s = s as *mut u8;
+    let c = c as u8;
+    let mut i = 0;
+    for i in 0..n {
+        if *s.offset(i as isize) == c {
+            return s.offset(i as isize) as *mut c_void;
+        }
+    }
+    ptr::null_mut()
 }
 
 // #[no_mangle]
diff --git a/tests/.gitignore b/tests/.gitignore
index 50e752e7fb61e18b5f0815ee9a06d94a95615ebc..0c582647bae5c7d29712cb26e55a69c6df7dc1ec 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -20,6 +20,7 @@
 /link
 /link.out
 /math
+/mem
 /setid
 /sleep
 /pipe
diff --git a/tests/Makefile b/tests/Makefile
index 7058a87c833e1666a56217ee610badab982e0a99..0726ba101ba745a2b509f969758060414efb1483 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -16,6 +16,7 @@ BINS=\
 	getid \
 	link \
 	math \
+	mem \
 	pipe \
 	printf \
 	rmdir \
diff --git a/tests/mem.c b/tests/mem.c
new file mode 100644
index 0000000000000000000000000000000000000000..cc104cbb9290c3ada258d0219d45996e74487cff
--- /dev/null
+++ b/tests/mem.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main(int argc, char ** argv) {
+	printf("# mem #\n");
+	char arr[100];
+	memset(arr, 0, 100); // Compiler builtin, should work
+	arr[50] = 1;
+	if ((size_t)memchr((void *)arr, 1, 100) - (size_t)arr != 50) {
+		printf("Incorrect memchr\n");
+		exit(1);
+	}
+	printf("Correct memchr\n");
+	char arr2[51];
+	memset(arr2, 0, 51); // Compiler builtin, should work
+	memccpy((void *)arr2, (void *)arr, 1, 100);
+	if (arr[50] != 1) {
+		printf("Incorrect memccpy\n");
+		exit(1);
+	}
+	printf("Correct memccpy\n");
+}