From 9325183b211905673ac2b550c108ced32f1e7189 Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jeremy@system76.com>
Date: Sat, 1 Dec 2018 08:55:02 -0700
Subject: [PATCH] Fix strcat

---
 src/header/string/mod.rs            | 24 +++++++++++++-----------
 tests/Makefile                      |  1 +
 tests/expected/string/strcat.stderr |  0
 tests/expected/string/strcat.stdout |  2 ++
 tests/string/strcat.c               | 12 ++++++++++++
 5 files changed, 28 insertions(+), 11 deletions(-)
 create mode 100644 tests/expected/string/strcat.stderr
 create mode 100644 tests/expected/string/strcat.stdout
 create mode 100644 tests/string/strcat.c

diff --git a/src/header/string/mod.rs b/src/header/string/mod.rs
index 1e1d018b..48788f2b 100644
--- a/src/header/string/mod.rs
+++ b/src/header/string/mod.rs
@@ -147,11 +147,6 @@ pub unsafe extern "C" fn memset(s: *mut c_void, c: c_int, n: size_t) -> *mut c_v
     s
 }
 
-#[no_mangle]
-pub unsafe extern "C" fn strcat(s1: *mut c_char, s2: *const c_char) -> *mut c_char {
-    strncat(s1, s2, usize::MAX)
-}
-
 #[no_mangle]
 pub unsafe extern "C" fn strchr(mut s: *const c_char, c: c_int) -> *mut c_char {
     let c = c as c_char;
@@ -283,18 +278,25 @@ pub unsafe extern "C" fn strnlen(s: *const c_char, size: size_t) -> size_t {
     i as size_t
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn strcat(s1: *mut c_char, s2: *const c_char) -> *mut c_char {
+    strncat(s1, s2, usize::MAX)
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn strncat(s1: *mut c_char, s2: *const c_char, n: size_t) -> *mut c_char {
-    let mut idx = strlen(s1 as *const _) as isize;
-    for i in 0..n as isize {
-        if *s2.offset(i) == 0 {
+    let len = strlen(s1 as *const c_char);
+    let mut i = 0;
+    while i < n {
+        let b = *s2.offset(i as isize);
+        if b == 0 {
             break;
         }
 
-        *s1.offset(idx) = *s2.offset(i);
-        idx += 1;
+        *s1.offset((len + i) as isize) = b;
+        i += 1;
     }
-    *s1.offset(idx) = 0;
+    *s1.offset((len + i) as isize) = 0;
 
     s1
 }
diff --git a/tests/Makefile b/tests/Makefile
index 609d6b4c..163a5041 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -46,6 +46,7 @@ EXPECT_BINS=\
 	stdlib/strtoul \
 	stdlib/system \
 	string/mem \
+	string/strcat \
 	string/strchr \
 	string/strcpy \
 	string/strcspn \
diff --git a/tests/expected/string/strcat.stderr b/tests/expected/string/strcat.stderr
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/expected/string/strcat.stdout b/tests/expected/string/strcat.stdout
new file mode 100644
index 00000000..10bda518
--- /dev/null
+++ b/tests/expected/string/strcat.stdout
@@ -0,0 +1,2 @@
+hello world
+hello world
diff --git a/tests/string/strcat.c b/tests/string/strcat.c
new file mode 100644
index 00000000..6913c557
--- /dev/null
+++ b/tests/string/strcat.c
@@ -0,0 +1,12 @@
+#include <string.h>
+#include <stdio.h>
+
+int main(int argc, char* argv[]) {
+    char dest1[12] = "hello";
+	  printf("%s\n", strcat(dest1, " world")); // should be hello world
+
+    char dest2[12] = "hello";
+  	printf("%s\n", strncat(dest2, " world foobar", 6)); // should be hello world
+
+    return 0;
+}
-- 
GitLab