diff --git a/src/string/src/lib.rs b/src/string/src/lib.rs
index bbb1a53c694a33b8063f0e4b7c2c7f55d49c2772..81e15e819fc660e7c5f40bb3ffac8f7775676035 100644
--- a/src/string/src/lib.rs
+++ b/src/string/src/lib.rs
@@ -39,7 +39,6 @@ pub unsafe extern "C" fn memccpy(
 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;
@@ -90,8 +89,16 @@ pub unsafe extern "C" fn strcat(s1: *mut c_char, s2: *const c_char) -> *mut c_ch
 }
 
 #[no_mangle]
-pub extern "C" fn strchr(s: *const c_char, c: c_int) -> *mut c_char {
-    unimplemented!();
+pub unsafe extern "C" fn strchr(s: *const c_char, c: c_int) -> *mut c_char {
+    let c = c as i8;
+    let mut i = 0;
+    while *s.offset(i) != 0 {
+        if *s.offset(i) == c {
+            return s.offset(i) as *mut c_char;
+        }
+        i += 1;
+    }
+    ptr::null_mut()
 }
 
 #[no_mangle]
@@ -110,8 +117,33 @@ pub unsafe extern "C" fn strcpy(s1: *mut c_char, s2: *const c_char) -> *mut c_ch
 }
 
 #[no_mangle]
-pub extern "C" fn strcspn(s1: *const c_char, s2: *const c_char) -> c_ulong {
-    unimplemented!();
+pub unsafe extern "C" fn strcspn(s1: *const c_char, s2: *const c_char) -> c_ulong {
+    use core::mem;
+
+    let s1 = s1 as *const u8;
+    let s2 = s2 as *const u8;
+
+    // The below logic is effectively ripped from the musl implementation
+
+    let mut byteset = [0u8; 32 / mem::size_of::<usize>()];
+
+    let mut i = 0;
+    while *s2.offset(i) != 0 {
+        byteset[(*s2.offset(i) as usize) / (8 * mem::size_of::<usize>())] |=
+            1 << (*s2.offset(i) as usize % (8 * mem::size_of::<usize>()));
+        i += 1;
+    }
+
+    i = 0; // reset
+    while *s2.offset(i) != 0 {
+        if byteset[(*s2.offset(i) as usize) / (8 * mem::size_of::<usize>())]
+            & 1 << (*s2.offset(i) as usize % (8 * mem::size_of::<usize>())) > 0
+        {
+            break;
+        }
+        i += 1;
+    }
+    i as u64
 }
 
 #[no_mangle]
@@ -237,8 +269,33 @@ pub unsafe extern "C" fn strrchr(s: *const c_char, c: c_int) -> *mut c_char {
 }
 
 #[no_mangle]
-pub extern "C" fn strspn(s1: *const c_char, s2: *const c_char) -> c_ulong {
-    unimplemented!();
+pub unsafe extern "C" fn strspn(s1: *const c_char, s2: *const c_char) -> c_ulong {
+    use core::mem;
+
+    let s1 = s1 as *const u8;
+    let s2 = s2 as *const u8;
+
+    // The below logic is effectively ripped from the musl implementation
+
+    let mut byteset = [0u8; 32 / mem::size_of::<usize>()];
+
+    let mut i = 0;
+    while *s2.offset(i) != 0 {
+        byteset[(*s2.offset(i) as usize) / (8 * mem::size_of::<usize>())] |=
+            1 << (*s2.offset(i) as usize % (8 * mem::size_of::<usize>()));
+        i += 1;
+    }
+
+    i = 0; // reset
+    while *s2.offset(i) != 0 {
+        if byteset[(*s2.offset(i) as usize) / (8 * mem::size_of::<usize>())]
+            & 1 << (*s2.offset(i) as usize % (8 * mem::size_of::<usize>())) < 1
+        {
+            break;
+        }
+        i += 1;
+    }
+    i as u64
 }
 
 #[no_mangle]
diff --git a/tests/.gitignore b/tests/.gitignore
index 0c582647bae5c7d29712cb26e55a69c6df7dc1ec..929fcc62d71ecb4731df70568aeaf5dd358dab3e 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -30,5 +30,8 @@
 /sprintf
 /stdlib/strtol
 /string/strncmp
+/string/strcspn
+/string/strchr
+/string/strspn
 /unlink
 /write
diff --git a/tests/Makefile b/tests/Makefile
index 8ca12a9a8d59cc50bd5070260e3afd5d4a26e19d..ea41ffa7a2a7761ab75e4e116579d9ef4276f051 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -25,7 +25,10 @@ BINS=\
 	sprintf \
 	stdlib/strtol \
 	string/strncmp \
+	string/strcspn \
+	string/strchr \
 	string/strrchr \
+	string/strspn \
 	unlink \
 	write
 
diff --git a/tests/string/strchr.c b/tests/string/strchr.c
new file mode 100644
index 0000000000000000000000000000000000000000..929c22bede3537694eb577e5ba15c4d76fb9dffb
--- /dev/null
+++ b/tests/string/strchr.c
@@ -0,0 +1,10 @@
+#include <string.h>
+#include <stdio.h>
+
+int main(int argc, char* argv[]) {
+	printf("%s\n", strchr("hello", 'e')); // should be ello
+	printf("%s\n", strchr("world", 'l')); // should be ld
+	printf("%s\n", strchr("world", 0)); // should be ''
+
+    return 0;
+}
diff --git a/tests/string/strcspn.c b/tests/string/strcspn.c
new file mode 100644
index 0000000000000000000000000000000000000000..fa433d7e4f76cdd892ec2cde1a0f0fc899b6fbba
--- /dev/null
+++ b/tests/string/strcspn.c
@@ -0,0 +1,9 @@
+#include <string.h>
+#include <stdio.h>
+
+int main(int argc, char* argv[]) {
+	printf("%ld\n", strcspn("hello", "world")); // should be 2
+	printf("%ld\n", strcspn("banana", "world")); // should be 6
+
+    return 0;
+}
diff --git a/tests/string/strspn.c b/tests/string/strspn.c
new file mode 100644
index 0000000000000000000000000000000000000000..9e4fc70c5b955f5f598d16a0bc85ff50a77a7c42
--- /dev/null
+++ b/tests/string/strspn.c
@@ -0,0 +1,10 @@
+#include <string.h>
+#include <stdio.h>
+
+int main(int argc, char* argv[]) {
+	printf("%lu\n", strspn("hello", "hello")); // should be 5
+	printf("%lu\n", strspn("world", "wendy")); // should be 1
+	printf("%lu\n", strspn("banana", "apple")); // should be 0
+
+    return 0;
+}