diff options
Diffstat (limited to 'src/string.c')
-rw-r--r-- | src/string.c | 73 |
1 files changed, 54 insertions, 19 deletions
diff --git a/src/string.c b/src/string.c index c14f1b5..ae19271 100644 --- a/src/string.c +++ b/src/string.c @@ -27,6 +27,7 @@ * all others pass through */ enum HX_quote_selector { + HXQUOTE_ALWAYS, HXQUOTE_ACCEPT, HXQUOTE_REJECT, }; @@ -211,6 +212,8 @@ EXPORT_SYMBOL char **HX_split(const char *str, const char *delim, *cp = max; ret = malloc(sizeof(char *) * (*cp + 1)); + if (ret == nullptr) + return nullptr; ret[*cp] = NULL; { @@ -378,20 +381,48 @@ EXPORT_SYMBOL char *HX_stpltrim(const char *p) return const_cast1(char *, p); } +/** + * Helper for substr() function for dealing with negative off/len values + * @z: total length of string + * @offset: n>=0 specifies offset from the start, + * n<0 specifies offset from the end + * @len: "length"; n>=0 specifies length to copy (from @offset), + * n<0 specifies the byte relative to the end at which to stop + * + * @abstart: (result) absolute start + * @retval: (result) absolute length to copy (from *@abstart) + */ +size_t HX_substr_helper(size_t z, long offset, long len, size_t *start) +{ + if (offset >= 0) + *start = offset; + else if (offset == LONG_MIN) + *start = z + -static_cast(size_t, LONG_MIN); + else + *start = z >= static_cast(unsigned long, -offset) ? z + offset : z; + + size_t end; + if (len >= 0) + end = *start < SIZE_MAX - len ? *start + len : SIZE_MAX; + else if (len == LONG_MIN) + end = z + -static_cast(unsigned long, LONG_MIN); + else + end = z >= static_cast(unsigned long, -len) ? z + len : 0; + if (end > z) + end = z; + return end > *start ? end - *start : 0; +} + /* supports negative offsets like scripting languages */ EXPORT_SYMBOL char *HX_strmid(const char *expr, long offset, long length) { - char *buffer; - - if (offset < 0) - offset = strlen(expr) + offset; - if (length < 0) - length = strlen(expr) - offset + length; - if ((buffer = malloc(length + 1)) == NULL) + size_t start = 0, tocopy = HX_substr_helper(strlen(expr), offset, length, &start); + char *buffer = malloc(tocopy + 1); + if (buffer == nullptr) return NULL; - - expr += offset; - return HX_strlcpy(buffer, expr, length + 1); + memcpy(buffer, &expr[start], tocopy); + buffer[tocopy] = '\0'; + return buffer; } EXPORT_SYMBOL char *HX_strndup(const char *src, size_t size) @@ -773,7 +804,7 @@ static size_t HX_quoted_size(const char *s, unsigned int type) EXPORT_SYMBOL char *HX_strquote(const char *src, unsigned int type, char **free_me) { - const struct HX_quote_rule *rule; + const struct HX_quote_rule *rule = nullptr; bool do_quote; char *tmp; @@ -782,15 +813,19 @@ EXPORT_SYMBOL char *HX_strquote(const char *src, unsigned int type, return NULL; } /* If quote_chars is NULL, it is clear all chars are to be encoded. */ - rule = &HX_quote_rules[type]; - if (type >= ARRAY_SIZE(HX_quote_rules) || rule->chars == NULL) + if (type >= ARRAY_SIZE(HX_quote_rules)) { do_quote = true; - else if (rule->selector == HXQUOTE_REJECT) - do_quote = strpbrk(src, rule->chars) != NULL; - else if (rule->selector == HXQUOTE_ACCEPT) - do_quote = HX_strchr2(src, rule->chars) != NULL; - else - do_quote = false; + } else { + rule = &HX_quote_rules[type]; + if (rule->selector == HXQUOTE_ALWAYS) + do_quote = true; + else if (rule->selector == HXQUOTE_REJECT) + do_quote = strpbrk(src, rule->chars) != NULL; + else if (rule->selector == HXQUOTE_ACCEPT) + do_quote = HX_strchr2(src, rule->chars) != NULL; + else + do_quote = false; + } /* * free_me == NULL implies that we always allocate, even if * there is nothing to quote. |