summaryrefslogtreecommitdiff
path: root/pith/charconv
diff options
context:
space:
mode:
authorEduardo Chappa <chappa@washington.edu>2021-05-31 17:18:47 -0600
committerEduardo Chappa <chappa@washington.edu>2021-05-31 17:18:47 -0600
commite10411bf0ecb248b65ca83882e945e15f906a6d4 (patch)
tree1a7bedd8085c8dfca3055b5d4b96a2b08414ba8e /pith/charconv
parentf17aaf0dc56c44e220f51f10b898b8c4a20f9dac (diff)
downloadalpine-e10411bf0ecb248b65ca83882e945e15f906a6d4.tar.xz
* Bug fix: Memory corruption when alpine searches for a string that is
an incomplete utf8 string in a local folder. This could happen by chopping a string to make it fit a buffer without regard to its content. We fix the string so that chopping it does not damage it. Reported by Andrew.
Diffstat (limited to 'pith/charconv')
-rw-r--r--pith/charconv/utf8.c43
-rw-r--r--pith/charconv/utf8.h1
2 files changed, 44 insertions, 0 deletions
diff --git a/pith/charconv/utf8.c b/pith/charconv/utf8.c
index 6b1e2e9d..ee5ab852 100644
--- a/pith/charconv/utf8.c
+++ b/pith/charconv/utf8.c
@@ -683,6 +683,49 @@ ucs4_to_utf8_cpystr_n(UCS *ucs4src, int ucs4src_len)
return ((char *) ret);
}
+/*
+ * Similar to above but copy what is possible to a
+ * string of a size at most the given retlen.
+ */
+char *
+ucs4_to_utf8_n_cpystr(UCS *ucs4src, int retlen)
+{
+ unsigned char *ret = NULL;
+ unsigned char *writeptr;
+ int i, oldlen, len;
+
+ if(!ucs4src)
+ return NULL;
+
+ /*
+ * Over-allocate and then resize at the end.
+ */
+
+ /* count characters in source */
+ for(i = 0; ucs4src[i]; i++)
+ ;
+
+ ret = (unsigned char *) fs_get((6*i + 1) * sizeof(unsigned char));
+ memset(ret, 0, (6*i + 1) * sizeof(unsigned char));
+
+ writeptr = ret;
+ oldlen = len = 0;
+ for(i = 0; ucs4src[i] && (len < retlen); i++){
+ oldlen = len;
+ writeptr = utf8_put(writeptr, (unsigned long) ucs4src[i]);
+ len = strlen(ret);
+ }
+ if(len > retlen){
+ ret[oldlen] = '\0';
+ len = oldlen;
+ }
+
+ /* get rid of excess size */
+ fs_resize((void **) &ret, (len + 1) * sizeof(unsigned char));
+
+ return ((char *) ret);
+}
+
#ifdef _WINDOWS
/*
diff --git a/pith/charconv/utf8.h b/pith/charconv/utf8.h
index f9597cbf..954821cc 100644
--- a/pith/charconv/utf8.h
+++ b/pith/charconv/utf8.h
@@ -66,6 +66,7 @@ UCS *ucs4_particular_width(UCS*, int);
UCS *utf8_to_ucs4_cpystr(char *);
char *ucs4_to_utf8_cpystr(UCS *);
char *ucs4_to_utf8_cpystr_n(UCS *, int);
+char *ucs4_to_utf8_n_cpystr(UCS *, int);
#ifdef _WINDOWS
LPTSTR utf8_to_lptstr(LPSTR);
LPSTR lptstr_to_utf8(LPTSTR);