Skip to content

Commit

Permalink
Merge pull request #231 from 'avoid-alloca'
Browse files Browse the repository at this point in the history
  • Loading branch information
eli-schwartz committed Feb 11, 2024
2 parents 4a75ae3 + 49219cc commit e8ef87a
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 78 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
5 changes: 0 additions & 5 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,7 @@ config.set('WITH_LIBIDN', enable_runtime == 'libidn')
config.set('ENABLE_BUILTIN', enable_builtin)
config.set('HAVE_UNISTD_H', cc.check_header('unistd.h'))
config.set('HAVE_STDINT_H', cc.check_header('stdint.h'))
config.set('HAVE_ALLOCA_H', cc.check_header('alloca.h'))
config.set('HAVE_DIRENT_H', cc.check_header('dirent.h'))
config.set('HAVE_ALLOCA', cc.has_function('alloca'))
config.set('HAVE_STRNDUP', cc.has_function('strndup'))
config.set('HAVE_CLOCK_GETTIME', cc.has_function('clock_gettime'))
config.set('HAVE_FMEMOPEN', cc.has_function('fmemopen'))
Expand Down Expand Up @@ -127,9 +125,6 @@ if cc.get_id() == 'msvc'
add_project_arguments('-Dsnprintf=_snprintf', language: 'c')
endif
endif
if cc.has_header_symbol('malloc.h', '_alloca')
add_project_arguments('-Dalloca=_alloca', language: 'c')
endif
endif

subdir('include')
Expand Down
48 changes: 27 additions & 21 deletions src/psl.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,8 @@ 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>
#else
# include <malloc.h>
#endif

#ifdef WITH_LIBICU
Expand Down Expand Up @@ -1753,23 +1749,31 @@ psl_error_t psl_str_to_utf8lower(const char *str, const char *encoding, const ch
}

#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 @@ -1779,13 +1783,13 @@ psl_error_t psl_str_to_utf8lower(const char *str, const char *encoding, const ch

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 @@ -1813,11 +1817,13 @@ psl_error_t psl_str_to_utf8lower(const char *str, const char *encoding, const ch
/* 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
7 changes: 7 additions & 0 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,20 @@ PSL_TESTS = test-is-public test-is-public-all test-is-cookie-domain-acceptable

if ENABLE_BUILTIN
PSL_TESTS += test-is-public-builtin test-registrable-domain
test_is_public_builtin_SOURCES = test-is-public-builtin.c $(common_SOURCES)
test_registrable_domain_SOURCES = test-registrable-domain.c $(common_SOURCES)
endif

check_PROGRAMS = $(PSL_TESTS)

TESTS_ENVIRONMENT = TESTS_VALGRIND="@VALGRIND_ENVIRONMENT@"
TESTS = $(PSL_TESTS)

common_SOURCES = common.c common.h
test_is_public_SOURCES = test-is-public.c $(common_SOURCES)
test_is_public_all_SOURCES = test-is-public-all.c $(common_SOURCES)
test_is_cookie_domain_acceptable_SOURCES = test-is-cookie-domain-acceptable.c $(common_SOURCES)

# dafsa.psl and dafsa_ascii.psl must be created before any test is executed
# check-local target works in parallel to the tests, so the test suite will likely fail
BUILT_SOURCES = psl.dafsa psl_ascii.dafsa
Expand Down
48 changes: 48 additions & 0 deletions tests/common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright(c) 2014-2024 Tim Ruehsen
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* This file is part of the test suite of libpsl.
*/

#include <stdio.h> // snprintf
#include <stdlib.h> // exit, system
#include <string.h> // strlen
#if defined _WIN32
# include <malloc.h>
#endif

int run_valgrind(const char *valgrind, const char *executable)
{
char cmd[BUFSIZ];
int n, rc;

n = snprintf(cmd, sizeof(cmd), "TESTS_VALGRIND="" %s %s", valgrind, executable);
if ((unsigned)n >= sizeof(cmd)) {
printf("Valgrind command line is too long (>= %u)\n", (unsigned) sizeof(cmd));
return EXIT_FAILURE;
}

if ((rc = system(cmd))) {
printf("Failed to execute with '%s' (system() returned %d)\n", valgrind, rc);
}

return rc ? EXIT_FAILURE : EXIT_SUCCESS;
}
38 changes: 38 additions & 0 deletions tests/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright(c) 2014-2024 Tim Ruehsen
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* This file is part of the test suite of libpsl.
*/

#ifndef COMMON_H
#define COMMON_H

#ifdef __cplusplus
extern "C" {
#endif

int run_valgrind(const char *valgrind, const char *executable);

#ifdef __cplusplus
}
#endif

#endif /* COMMON_H */
9 changes: 6 additions & 3 deletions tests/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@ if enable_builtin
tests += ['test-is-public-builtin', 'test-registrable-domain']
endif

libtestcommon = static_library('testcommon', 'common.c',
build_by_default: false)

foreach test_name : tests
source = test_name + '.c'
exe = executable(test_name, source,
sources = [test_name + '.c', 'common.c', 'common.h']
exe = executable(test_name, sources,
build_by_default: false,
c_args : tests_cargs,
link_with : libpsl,
link_with : [libpsl, libtestcommon],
include_directories : configinc,
link_language : link_language,
dependencies : [libpsl_dep, networking_deps])
Expand Down
10 changes: 2 additions & 8 deletions tests/test-is-cookie-domain-acceptable.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#endif

#include <libpsl.h>
#include "common.h"

#define countof(a) (sizeof(a)/sizeof(*(a)))

Expand Down Expand Up @@ -130,11 +128,7 @@ int main(int argc, const char * const *argv)
const char *valgrind = getenv("TESTS_VALGRIND");

if (valgrind && *valgrind) {
size_t cmdsize = strlen(valgrind) + strlen(argv[0]) + 32;
char *cmd = alloca(cmdsize);

snprintf(cmd, cmdsize, "TESTS_VALGRIND="" %s %s", valgrind, argv[0]);
return system(cmd) != 0;
return run_valgrind(valgrind, argv[0]);
}
}

Expand Down
14 changes: 5 additions & 9 deletions tests/test-is-public-all.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,12 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#elif defined _WIN32
#if defined _WIN32
# include <malloc.h>
#endif

#include <libpsl.h>
#include "common.h"

static int
ok,
Expand Down Expand Up @@ -120,7 +119,7 @@ static void test_psl_entry(const psl_ctx_t *psl, const char *domain, int type)
} else if (*domain == '*') { /* a wildcard, e.g. *.ck or *.platform.sh */
/* '*.platform.sh' -> 'y.x.platform.sh' */
size_t len = strlen(domain);
char *xdomain = alloca(len + 3);
char *xdomain = malloc(len + 3);

memcpy(xdomain, "y.x", 3);
memcpy(xdomain + 3, domain + 1, len);
Expand All @@ -129,6 +128,7 @@ static void test_psl_entry(const psl_ctx_t *psl, const char *domain, int type)
test_type_any(psl, xdomain + 2, type, 1); /* random wildcard-matching domain is a PS... */
test_type_any(psl, xdomain, type, 0); /* ... but sub domain is not */

free(xdomain);
} else {
test_type_any(psl, domain, type, 1); /* Any normal PSL entry */
}
Expand Down Expand Up @@ -230,11 +230,7 @@ int main(int argc, const char * const *argv)
const char *valgrind = getenv("TESTS_VALGRIND");

if (valgrind && *valgrind) {
size_t cmdsize = strlen(valgrind) + strlen(argv[0]) + 32;
char *cmd = alloca(cmdsize);

snprintf(cmd, cmdsize, "TESTS_VALGRIND="" %s %s", valgrind, argv[0]);
return system(cmd) != 0;
return run_valgrind(valgrind, argv[0]);
}
}

Expand Down
12 changes: 2 additions & 10 deletions tests/test-is-public-builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#elif defined _WIN32
# include <malloc.h>
#endif

#include <libpsl.h>
#include "common.h"

#define countof(a) (sizeof(a)/sizeof(*(a)))

Expand Down Expand Up @@ -141,11 +137,7 @@ int main(int argc, const char * const *argv)
const char *valgrind = getenv("TESTS_VALGRIND");

if (valgrind && *valgrind) {
size_t cmdsize = strlen(valgrind) + strlen(argv[0]) + 32;
char *cmd = alloca(cmdsize);

snprintf(cmd, cmdsize, "TESTS_VALGRIND="" %s %s", valgrind, argv[0]);
return system(cmd) != 0;
return run_valgrind(valgrind, argv[0]);
}
}

Expand Down
12 changes: 2 additions & 10 deletions tests/test-is-public.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#elif defined _WIN32
# include <malloc.h>
#endif

#include <libpsl.h>
#include "common.h"

#define countof(a) (sizeof(a)/sizeof(*(a)))

Expand Down Expand Up @@ -195,11 +191,7 @@ int main(int argc, const char * const *argv)
const char *valgrind = getenv("TESTS_VALGRIND");

if (valgrind && *valgrind) {
size_t cmdsize = strlen(valgrind) + strlen(argv[0]) + 32;
char *cmd = alloca(cmdsize);

snprintf(cmd, cmdsize, "TESTS_VALGRIND="" %s %s", valgrind, argv[0]);
return system(cmd) != 0;
return run_valgrind(valgrind, argv[0]);
}
}

Expand Down
Loading

0 comments on commit e8ef87a

Please sign in to comment.