util: fixed place where we could look one byte past end of string
[ira/wip.git] / lib / util / charset / util_unistr.c
index c90b675ded67a8f87b0e16d1203b3381ceea7776..045aa4a3e3f4922a4df2c86d13e33425b5d05ae1 100644 (file)
@@ -133,7 +133,7 @@ _PUBLIC_ int strncasecmp_m(const char *s1, const char *s2, size_t n)
                n--;
 
                c1 = next_codepoint_convenience(iconv_convenience, s1, &size1);
-               c2 = next_codepoint_convenienceconv_convenience, s2, &size2);
+               c2 = next_codepoint_convenience(iconv_convenience, s2, &size2);
 
                s1 += size1;
                s2 += size2;
@@ -272,7 +272,7 @@ _PUBLIC_ size_t strlen_m(const char *s)
 
        while (*s) {
                size_t c_size;
-               codepoint_t c = next_codepoint(ic, s, &c_size);
+               codepoint_t c = next_codepoint_convenience(ic, s, &c_size);
                if (c < 0x10000) {
                        count += 1;
                } else {
@@ -297,6 +297,25 @@ _PUBLIC_ size_t strlen_m_term(const char *s)
        return strlen_m(s) + 1;
 }
 
+/*
+ * Weird helper routine for the winreg pipe: If nothing is around, return 0,
+ * if a string is there, include the terminator.
+ */
+
+_PUBLIC_ size_t strlen_m_term_null(const char *s)
+{
+       size_t len;
+       if (!s) {
+               return 0;
+       }
+       len = strlen_m(s);
+       if (len == 0) {
+               return 0;
+       }
+
+       return len+1;
+}
+
 /**
  Strchr and strrchr_m are a bit complex on general multi-byte strings. 
 **/
@@ -344,7 +363,7 @@ _PUBLIC_ char *strrchr_m(const char *s, char c)
 
        while (*s) {
                size_t size;
-               codepoint_t c2 = next_codepoint(ic, s, &size);
+               codepoint_t c2 = next_codepoint_convenience(ic, s, &size);
                if (c2 == c) {
                        ret = discard_const_p(char, s);
                }
@@ -425,7 +444,7 @@ _PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char *src)
 
                c = tolower_m(c);
 
-               c_size = push_codepoint(iconv_convenience, dest+size, c);
+               c_size = push_codepoint_convenience(iconv_convenience, dest+size, c);
                if (c_size == -1) {
                        talloc_free(dest);
                        return NULL;
@@ -464,14 +483,14 @@ _PUBLIC_ char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n)
                return NULL;
        }
 
-       while (*src && n--) {
+       while (n-- && *src) {
                size_t c_size;
-               codepoint_t c = next_codepoint(iconv_convenience, src, &c_size);
+               codepoint_t c = next_codepoint_convenience(iconv_convenience, src, &c_size);
                src += c_size;
 
                c = toupper_m(c);
 
-               c_size = push_codepoint(iconv_convenience, dest+size, c);
+               c_size = push_codepoint_convenience(iconv_convenience, dest+size, c);
                if (c_size == -1) {
                        talloc_free(dest);
                        return NULL;
@@ -532,7 +551,7 @@ _PUBLIC_ void strlower_m(char *s)
        while (*s) {
                size_t c_size, c_size2;
                codepoint_t c = next_codepoint_convenience(iconv_convenience, s, &c_size);
-               c_size2 = push_codepoint(iconv_convenience, d, tolower_m(c));
+               c_size2 = push_codepoint_convenience(iconv_convenience, d, tolower_m(c));
                if (c_size2 > c_size) {
                        DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n",
                                 c, tolower_m(c), (int)c_size, (int)c_size2));
@@ -571,7 +590,7 @@ _PUBLIC_ void strupper_m(char *s)
        while (*s) {
                size_t c_size, c_size2;
                codepoint_t c = next_codepoint_convenience(iconv_convenience, s, &c_size);
-               c_size2 = push_codepoint(iconv_convenience, d, toupper_m(c));
+               c_size2 = push_codepoint_convenience(iconv_convenience, d, toupper_m(c));
                if (c_size2 > c_size) {
                        DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n",
                                 c, toupper_m(c), (int)c_size, (int)c_size2));
@@ -637,7 +656,7 @@ static ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flag
        if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
                src_len++;
 
-       return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
+       return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, false);
 }
 
 /**
@@ -649,11 +668,11 @@ static ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flag
  * @returns The number of bytes occupied by the string in the destination
  *         or -1 in case of error.
  **/
-_PUBLIC_ ssize_t push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
+_PUBLIC_ bool push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size)
 {
        size_t src_len = strlen(src)+1;
        *dest = NULL;
-       return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest);
+       return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest, converted_size, false);
 }
 
 
@@ -687,7 +706,7 @@ static ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t s
                }
        }
 
-       ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
+       ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, false);
 
        if (dest_len)
                dest[MIN(ret, dest_len-1)] = 0;
@@ -740,7 +759,7 @@ static ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags
        /* ucs2 is always a multiple of 2 bytes */
        dest_len &= ~1;
 
-       ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len);
+       ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len, false);
        if (ret == (size_t)-1) {
                return 0;
        }
@@ -760,11 +779,11 @@ static ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags
  * @returns The number of bytes occupied by the string in the destination
  *         or -1 in case of error.
  **/
-_PUBLIC_ ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src)
+_PUBLIC_ bool push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src, size_t *converted_size)
 {
        size_t src_len = strlen(src)+1;
        *dest = NULL;
-       return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, dest);
+       return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, (void **)dest, converted_size, false);
 }
 
 
@@ -776,11 +795,11 @@ _PUBLIC_ ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src)
  * @returns The number of bytes occupied by the string in the destination
  **/
 
-_PUBLIC_ ssize_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
+_PUBLIC_ bool push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size)
 {
        size_t src_len = strlen(src)+1;
        *dest = NULL;
-       return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest);
+       return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest, converted_size, false);
 }
 
 /**
@@ -816,7 +835,7 @@ static size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src
        if (src_len != (size_t)-1)
                src_len &= ~1;
        
-       ret = convert_string(CH_UTF16, CH_UNIX, src, src_len, dest, dest_len);
+       ret = convert_string(CH_UTF16, CH_UNIX, src, src_len, dest, dest_len, false);
        if (dest_len)
                dest[MIN(ret, dest_len-1)] = 0;
 
@@ -831,11 +850,11 @@ static size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src
  * @returns The number of bytes occupied by the string in the destination
  **/
 
-_PUBLIC_ ssize_t pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
+_PUBLIC_ bool pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size)
 {
        size_t src_len = strlen(src)+1;
        *dest = NULL;
-       return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest);
+       return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest, converted_size, false);
 }
 
 /**
@@ -846,11 +865,11 @@ _PUBLIC_ ssize_t pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src
  * @returns The number of bytes occupied by the string in the destination
  **/
 
-_PUBLIC_ ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const void *src)
+_PUBLIC_ bool pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src, size_t *converted_size)
 {
        size_t src_len = utf16_len(src);
        *dest = NULL;
-       return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest);
+       return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest, converted_size, false);
 }
 
 /**
@@ -861,11 +880,11 @@ _PUBLIC_ ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const void *src)
  * @returns The number of bytes occupied by the string in the destination
  **/
 
-_PUBLIC_ ssize_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
+_PUBLIC_ bool pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size)
 {
        size_t src_len = strlen(src)+1;
        *dest = NULL;
-       return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);
+       return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, converted_size, false);
 }
 
 /**
@@ -931,13 +950,18 @@ _PUBLIC_ ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_
  * @param destlen maximal length allowed for string
  * @returns the number of bytes occupied in the destination
  **/
-_PUBLIC_ ssize_t convert_string(charset_t from, charset_t to,
+_PUBLIC_ size_t convert_string(charset_t from, charset_t to,
                                void const *src, size_t srclen, 
-                               void *dest, size_t destlen)
+                               void *dest, size_t destlen, 
+                               bool allow_badcharcnv)
 {
-       return convert_string_convenience(get_iconv_convenience(), from, to, 
+       size_t ret;
+       if (!convert_string_convenience(get_iconv_convenience(), from, to, 
                                                                          src, srclen,
-                                                                         dest, destlen);
+                                                                         dest, destlen, &ret,
+                                                                         allow_badcharcnv))
+               return -1;
+       return ret;
 }
 
 /**
@@ -945,18 +969,22 @@ _PUBLIC_ ssize_t convert_string(charset_t from, charset_t to,
  *
  * @param srclen length of source buffer.
  * @param dest always set at least to NULL
+ * @param converted_size Size in bytes of the converted string
  * @note -1 is not accepted for srclen.
  *
- * @returns Size in bytes of the converted string; or -1 in case of error.
+ * @returns boolean indication whether the conversion succeeded
  **/
 
-_PUBLIC_ ssize_t convert_string_talloc(TALLOC_CTX *ctx, 
+_PUBLIC_ bool convert_string_talloc(TALLOC_CTX *ctx, 
                                       charset_t from, charset_t to, 
                                       void const *src, size_t srclen, 
-                                      void **dest)
+                                      void *dest, size_t *converted_size, 
+                                          bool allow_badcharcnv)
 {
        return convert_string_talloc_convenience(ctx, get_iconv_convenience(),
-                                                                                        from, to, src, srclen, dest);
+                                                                                        from, to, src, srclen, dest,
+                                                                                        converted_size, 
+                                                                                        allow_badcharcnv);
 }
 
 
@@ -964,3 +992,8 @@ _PUBLIC_ codepoint_t next_codepoint(const char *str, size_t *size)
 {
        return next_codepoint_convenience(get_iconv_convenience(), str, size);
 }
+
+_PUBLIC_ ssize_t push_codepoint(char *str, codepoint_t c)
+{
+       return push_codepoint_convenience(get_iconv_convenience(), str, c);
+}