From fe8fb9165c694e77d520c32177216bfe8004892e Mon Sep 17 00:00:00 2001
From: Damien George <damien.p.george@gmail.com>
Date: Thu, 2 Jan 2014 16:36:09 +0000
Subject: [PATCH] py: remove depedence on strcat and stpcpy.

This fixes Issue #29, and means the core is no longer dependent on
string functions, except strlen.
---
 py/compile.c | 18 +++++++++++++-----
 py/objstr.c  | 35 +++++++++++++++++++++++++++--------
 2 files changed, 40 insertions(+), 13 deletions(-)

diff --git a/py/compile.c b/py/compile.c
index fe22a9017..b00ab7ef6 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -1182,13 +1182,18 @@ void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q1, qstr *q2) {
                 len += strlen(qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])));
             }
             char *str = m_new(char, len + 1);
+            char *str_dest = str;
             str[0] = 0;
             for (int i = 0; i < n; i++) {
                 if (i > 0) {
-                    strcat(str, ".");
+                    *str_dest++ = '.';
                 }
-                strcat(str, qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])));
+                const char *str_src = qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
+                size_t str_src_len = strlen(str_src);
+                memcpy(str_dest, str_src, str_src_len);
+                str_dest += str_src_len;
             }
+            *str_dest = '\0';
             *q2 = qstr_from_str_take(str, len + 1);
             EMIT(import_name, *q2);
             if (is_as) {
@@ -2124,13 +2129,16 @@ void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
 
     // allocate memory for concatenated string/bytes
     char *cat_str = m_new(char, n_bytes + 1);
-    cat_str[0] = '\0';
 
     // concatenate string/bytes
+    char *s_dest = cat_str;
     for (int i = 0; i < n; i++) {
-        const char *str = qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
-        strcat(cat_str, str);
+        const char *s = qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
+        size_t s_len = strlen(s);
+        memcpy(s_dest, s, s_len);
+        s_dest += s_len;
     }
+    *s_dest = '\0';
 
     EMIT(load_const_str, qstr_from_str_take(cat_str, n_bytes + 1), string_kind == MP_PARSE_NODE_BYTES);
 }
diff --git a/py/objstr.c b/py/objstr.c
index 104a54bb3..48abf4951 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -36,9 +36,13 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
             if (MP_OBJ_IS_TYPE(rhs_in, &str_type)) {
                 // add 2 strings
                 const char *rhs_str = qstr_str(((mp_obj_str_t*)rhs_in)->qstr);
-                int alloc_len = strlen(lhs_str) + strlen(rhs_str) + 1;
+                size_t lhs_len = strlen(lhs_str);
+                size_t rhs_len = strlen(rhs_str);
+                int alloc_len = lhs_len + rhs_len + 1;
                 char *val = m_new(char, alloc_len);
-                stpcpy(stpcpy(val, lhs_str), rhs_str);
+                memcpy(val, lhs_str, lhs_len);
+                memcpy(val + lhs_len, rhs_str, rhs_len);
+                val[lhs_len + rhs_len] = '\0';
                 return mp_obj_new_str(qstr_from_str_take(val, alloc_len));
             }
             break;
@@ -50,9 +54,12 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
 mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
     assert(MP_OBJ_IS_TYPE(self_in, &str_type));
     mp_obj_str_t *self = self_in;
-    int required_len = strlen(qstr_str(self->qstr));
 
-    // process arg, count required chars
+    // get separation string
+    const char *sep_str = qstr_str(self->qstr);
+    size_t sep_len = strlen(sep_str);
+
+    // process args
     uint seq_len;
     mp_obj_t *seq_items;
     if (MP_OBJ_IS_TYPE(arg, &tuple_type)) {
@@ -62,23 +69,35 @@ mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
     } else {
         goto bad_arg;
     }
+
+    // count required length
+    int required_len = 0;
     for (int i = 0; i < seq_len; i++) {
         if (!MP_OBJ_IS_TYPE(seq_items[i], &str_type)) {
             goto bad_arg;
         }
+        if (i > 0) {
+            required_len += sep_len;
+        }
         required_len += strlen(qstr_str(mp_obj_str_get(seq_items[i])));
     }
 
     // make joined string
     char *joined_str = m_new(char, required_len + 1);
-    joined_str[0] = 0;
+    char *s_dest = joined_str;
     for (int i = 0; i < seq_len; i++) {
-        const char *s2 = qstr_str(mp_obj_str_get(seq_items[i]));
         if (i > 0) {
-            strcat(joined_str, qstr_str(self->qstr));
+            memcpy(s_dest, sep_str, sep_len);
+            s_dest += sep_len;
         }
-        strcat(joined_str, s2);
+        const char *s2 = qstr_str(mp_obj_str_get(seq_items[i]));
+        size_t s2_len = strlen(s2);
+        memcpy(s_dest, s2, s2_len);
+        s_dest += s2_len;
     }
+    *s_dest = '\0';
+
+    // return joined string
     return mp_obj_new_str(qstr_from_str_take(joined_str, required_len + 1));
 
 bad_arg:
-- 
GitLab