Skip to content

Commit

Permalink
Drop usage of alloca() in libpsl
Browse files Browse the repository at this point in the history
Reported-by: @rsbeckerca (github.com)
  • Loading branch information
rockdaboot committed Feb 4, 2024
1 parent 3ea39bd commit ed636bd
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 23 deletions.
2 changes: 0 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,6 @@ AC_ARG_WITH(psl-testfile,
PSL_TESTFILE="\$(top_srcdir)/list/tests/tests.txt")
AC_SUBST(PSL_TESTFILE)

# check for alloca / alloca.h
AC_FUNC_ALLOCA
AC_CHECK_FUNCS([strndup clock_gettime fmemopen nl_langinfo])

# check for dirent.h
Expand Down
47 changes: 26 additions & 21 deletions src/psl.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,7 @@ typedef SSIZE_T ssize_t;

#ifndef _WIN32
# include <arpa/inet.h>
#endif

#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#elif defined _WIN32
# include <malloc.h>
# include <malloc.h>
#endif

#ifdef WITH_LIBICU
Expand Down Expand Up @@ -1745,23 +1740,31 @@ psl_error_t psl_str_to_utf8lower(const char *str, const char *encoding PSL_UNUSE
}

#ifdef WITH_LIBICU
#define STACK_STRLENGTH 256
do {
size_t str_length = strlen(str);
UErrorCode status = 0;
UChar *utf16_dst, *utf16_lower;
int32_t utf16_dst_length;
char *utf8_lower;
int32_t utf16_dst_length, utf16_dst_size, utf16_lower_size, utf8_lower_size;
UConverter *uconv;
UChar utf16_dst_buf[STACK_STRLENGTH * 2 + 1];
UChar utf16_lower_buf[STACK_STRLENGTH * 2 + 1];
char utf8_lower_buf[STACK_STRLENGTH * 6 + 1];
size_t str_length = strlen(str);

if (str_length < 256) {
/* C89 allocation */
utf16_dst = alloca(sizeof(UChar) * (str_length * 2 + 1));
utf16_lower = alloca(sizeof(UChar) * (str_length * 2 + 1));
utf8_lower = alloca(str_length * 6 + 1);
if (str_length <= STACK_STRLENGTH) {
utf16_dst_size = countof(utf16_dst_buf);
utf16_lower_size = countof(utf16_lower_buf);
utf8_lower_size = countof(utf8_lower_buf);
utf16_dst = utf16_dst_buf;
utf16_lower = utf16_lower_buf;
utf8_lower = utf8_lower_buf;
} else {
utf16_dst = malloc(sizeof(UChar) * (str_length * 2 + 1));
utf16_lower = malloc(sizeof(UChar) * (str_length * 2 + 1));
utf8_lower = malloc(str_length * 6 + 1);
utf16_dst_size = utf16_lower_size = str_length * 2 + 1;
utf8_lower_size = str_length * 6 + 1;
utf16_dst = malloc(sizeof(UChar) * utf16_dst_size);
utf16_lower = malloc(sizeof(UChar) * utf16_lower_size);
utf8_lower = malloc(sizeof(char) * utf8_lower_size);

if (!utf16_dst || !utf16_lower || !utf8_lower) {
ret = PSL_ERR_NO_MEM;
Expand All @@ -1771,13 +1774,13 @@ psl_error_t psl_str_to_utf8lower(const char *str, const char *encoding PSL_UNUSE

uconv = ucnv_open(encoding, &status);
if (U_SUCCESS(status)) {
utf16_dst_length = ucnv_toUChars(uconv, utf16_dst, str_length * 2 + 1, str, str_length, &status);
utf16_dst_length = ucnv_toUChars(uconv, utf16_dst, utf16_dst_size, str, str_length, &status);
ucnv_close(uconv);

if (U_SUCCESS(status)) {
int32_t utf16_lower_length = u_strToLower(utf16_lower, str_length * 2 + 1, utf16_dst, utf16_dst_length, locale, &status);
int32_t utf16_lower_length = u_strToLower(utf16_lower, utf16_lower_size, utf16_dst, utf16_dst_length, locale, &status);
if (U_SUCCESS(status)) {
u_strToUTF8(utf8_lower, str_length * 6 + 1, NULL, utf16_lower, utf16_lower_length, &status);
u_strToUTF8(utf8_lower, utf8_lower_size, NULL, utf16_lower, utf16_lower_length, &status);
if (U_SUCCESS(status)) {
ret = PSL_SUCCESS;
if (lower) {
Expand Down Expand Up @@ -1805,11 +1808,13 @@ psl_error_t psl_str_to_utf8lower(const char *str, const char *encoding PSL_UNUSE
/* fprintf(stderr, "Failed to open converter for '%s' (status %d)\n", encoding, status); */
}
out:
if (str_length >= 256) {
if (utf16_dst != utf16_dst_buf)
free(utf16_dst);
if (utf16_lower != utf16_lower_buf)
free(utf16_lower);
if (utf8_lower != utf8_lower_buf)
free(utf8_lower);
}

} while (0);
#elif defined(WITH_LIBIDN2) || defined(WITH_LIBIDN)
do {
Expand Down

0 comments on commit ed636bd

Please sign in to comment.