Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement is_ip4() and is_ip6() to avoid network dependencies #228

Merged
merged 4 commits into from
Mar 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 1 addition & 15 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -299,19 +299,6 @@ elif test -n "$NEEDS_SOCKET" ; then
LIBS="$LIBS -lsocket"
elif test -n "$NEEDS_NSL" ; then
LIBS="$LIBS -lnsl"
else
# Platform dependant options
case "${host_os}" in
# MinGW / Windows
*mingw*)
# Select Windows NT/2000 and later, for WSAStringToAddressW()
CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x500"
# Needed for network support
LIBS="$LIBS -lws2_32"
;;
*)
;;
esac
fi

# Check for clock_gettime() used for performance measurement
Expand Down Expand Up @@ -356,8 +343,7 @@ AC_ARG_WITH(psl-testfile,
PSL_TESTFILE="\$(top_srcdir)/list/tests/tests.txt")
AC_SUBST(PSL_TESTFILE)

AC_CHECK_FUNCS([strdup strndup clock_gettime fmemopen nl_langinfo])
AC_CHECK_DECLS([strdup])
AC_CHECK_FUNCS([clock_gettime fmemopen nl_langinfo])
AC_CHECK_DECLS([localtime_r])

# check for dirent.h
Expand Down
2 changes: 1 addition & 1 deletion contrib/check-hard
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ echo "Running: make distclean"
make distclean > /dev/null || true

# We define _GNU_SOURCE to avoid warnings with missing prototypes.
# C89 does not know snprintf, strdup, strndup, popen, pclose
# C89 does not know snprintf, popen, pclose
CFLAGS="-std=gnu89 -pedantic -g -Wall -Wextra -Wstrict-prototypes -Wold-style-definition -Wwrite-strings -Wshadow -Wformat -Wformat-security -Wunreachable-code -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition"

CACHEFILE=$PWD/config_check.cache
Expand Down
2 changes: 1 addition & 1 deletion contrib/check-hard-meson
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ set -e
set -u

# We define _GNU_SOURCE to avoid warnings with missing prototypes.
# C89 does not know snprintf, strdup, strndup, popen, pclose
# C89 does not know snprintf, popen, pclose
export CFLAGS="-std=gnu89 -pedantic -g -Wall -Wextra -Wstrict-prototypes -Wold-style-definition -Wwrite-strings -Wshadow -Wformat -Wformat-security -Wunreachable-code -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition"

ASAN_FLAGS="-fsanitize=address -fno-omit-frame-pointer -fsanitize-address-use-after-scope"
Expand Down
55 changes: 55 additions & 0 deletions contrib/mingw.static
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/bin/bash

set -e

# just in case...
unset CC
unset CXX

#PREFIX=i686-w64-mingw32
PREFIX=x86_64-w64-mingw32

#export PATH="/usr/$PREFIX/bin:$PATH"
export INSTALLDIR="$PWD/$PREFIX"
export PKG_CONFIG_PATH=$INSTALLDIR/lib/pkgconfig:/usr/$PREFIX/lib/pkgconfig
export PKG_CONFIG_LIBDIR="$INSTALLDIR/lib/pkgconfig"
export PKG_CONFIG="/usr/bin/${PREFIX}-pkg-config"
export CPPFLAGS="-I$INSTALLDIR/include"
export LDFLAGS="-L$INSTALLDIR/lib"

# without WINEPATH our local DLLs won't be find when running tests
export WINEPATH="$INSTALLDIR/bin;$INSTALLDIR/lib;/usr/$PREFIX/bin;/usr/$PREFIX/lib;$PWD/libwget/.libs;$GCCLIB"

# let mingw compiler be less verbose
export CFLAGS="-O2 -Wall -Wno-format"

rm -rf libiconv-*
wget -q -O- https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.17.tar.gz | tar xz
cd libiconv-*
./configure --build=x86_64-pc-linux-gnu --host=$PREFIX --disable-shared --enable-static --prefix=$INSTALLDIR
make -j$(nproc)
make install
cd ..

rm -rf libunistring-*
wget -q -O- https://ftp.gnu.org/gnu/libunistring/libunistring-latest.tar.gz | tar xz
cd libunistring-*
./configure --build=x86_64-pc-linux-gnu --host=$PREFIX --disable-shared --enable-static --prefix=$INSTALLDIR
make -j$(nproc)
make install
cd ..

rm -rf libidn2-*
wget -q -O- https://ftp.gnu.org/gnu/libidn/libidn2-latest.tar.gz | tar xz
cd libidn2-*
./configure --build=x86_64-pc-linux-gnu --host=$PREFIX --disable-shared --enable-static --disable-doc --prefix=$INSTALLDIR
make -j$(nproc)
make install
cd ..

# build libpsl
./autogen.sh
./configure --build=x86_64-pc-linux-gnu --host=$PREFIX --disable-shared --enable-static --disable-gtk-doc --enable-runtime=libidn2 --prefix=$INSTALLDIR
make clean
make -j$(nproc)
make check -j$(nproc) LOG_COMPILER=wine
1 change: 0 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ 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_DIRENT_H', cc.check_header('dirent.h'))
config.set('HAVE_STRDUP', cc.has_function('strdup'))
config.set('HAVE_CLOCK_GETTIME', cc.has_function('clock_gettime'))
config.set('HAVE_FMEMOPEN', cc.has_function('fmemopen'))
config.set('HAVE_NL_LANGINFO', cc.has_function('nl_langinfo'))
Expand Down
3 changes: 0 additions & 3 deletions msvc/config.h.win32.in
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,6 @@
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1

/* Define to 1 if you have the `strndup' function. */
/* #undef HAVE_STRNDUP */

/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1

Expand Down
131 changes: 89 additions & 42 deletions src/psl.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,11 @@
#include <sys/types.h>
#include <sys/stat.h>

#ifdef _WIN32
# include <winsock2.h>
# include <ws2tcpip.h>
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <unistd.h>
#if defined(_WIN32) && (defined(WITH_LIBIDN2) || defined(WITH_LIBIDN))
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h> /* for GetACP() */
#endif

#if defined(_MSC_VER) && ! defined(ssize_t)
Expand All @@ -67,10 +65,8 @@ typedef SSIZE_T ssize_t;
# include <langinfo.h>
#endif

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

#ifdef WITH_LIBICU
Expand Down Expand Up @@ -320,22 +316,13 @@ static int suffix_init(psl_entry_t *suffix, const char *rule, size_t length)
return 0;
}

#ifndef HAVE_STRDUP
static char *strdup(const char *s)
static char *psl_strdup(const char *s)
{
char *p = malloc(strlen(s) + 1);
if (!p)
return NULL;
return strcpy(p, s);
}
#elif !HAVE_DECL_STRDUP
/*
* On Linux with
* CC=gcc CFLAGS="-Wall -Wextra -Wpedantic -std=c89" ./configure
* strdup isn't declared (warning: implicit declaration of function 'strdup').
*/
char *strdup(const char *);
#endif

#if !defined(WITH_LIBIDN) && !defined(WITH_LIBIDN2) && !defined(WITH_LIBICU)
/*
Expand Down Expand Up @@ -733,7 +720,7 @@ static int psl_idna_toASCII(psl_idna_t *idna, const char *utf8, char **ascii)

lookupname[bytes_written] = 0; /* u_strToUTF8() doesn't 0-terminate if dest is filled up */
} else {
if (!(lookupname = strdup(lookupname)))
if (!(lookupname = psl_strdup(lookupname)))
goto cleanup;
}

Expand Down Expand Up @@ -808,7 +795,7 @@ static int psl_idna_toASCII(psl_idna_t *idna, const char *utf8, char **ascii)

if (domain_to_punycode(utf8, lookupname, sizeof(lookupname)) == 0) {
if (ascii)
if ((*ascii = strdup(lookupname)))
if ((*ascii = psl_strdup(lookupname)))
ret = 0;
}
#endif
Expand Down Expand Up @@ -1602,30 +1589,90 @@ int psl_check_version_number(int version)

return PSL_VERSION_NUMBER;
}
/*
* Return true if 'src' is a valid dotted quad, else false.
* Assume that characters '0'..'9' have consecutive byte values.
* credit:
* inspired by Paul Vixie
*/
static int is_ip4(const char *s)
{
int i, n;
unsigned char c;

/* return whether hostname is an IP address or not */
static int isip(const char *hostname)
for (i = 0; i < 4; i++) {
if (!(c = *s++) || c < '0' || c > '9')
return 0;

n = c - '0';
if ((c = *s++) && c >= '0' && c <= '9') {
n = n * 10 + c - '0';
if ((c = *s++) && c >= '0' && c <= '9') {
n = n * 10 + c - '0';
if ((c = *s++) && c >= '0' && c <= '9') {
n = n * 10 + c - '0';
c = *s++;
}
}
}

if (n > 255)
return 0;

if (i < 3 && c != '.')
return 0;
}

return !c;
}

static int hexval(unsigned c)
{
#ifdef _WIN32
WCHAR wName[INET6_ADDRSTRLEN+1];
if (c - '0' < 10) return c - '0';
c |= 32;
if (c - 'a' < 6) return c - 'a' + 10;
return -1;
}

struct sockaddr_in addr = {0};
struct sockaddr_in6 addr6 = {0};
/*
* Original code taken from musl inet_pton(),
* which has a standard MIT license (https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT).
* Amended and simplified to out needs.
*/
static int is_ip6(const char *s)
{
int i, j, n, d, brk = -1, need_v4 = 0;

INT size = sizeof(addr);
INT size6 = sizeof(addr6);
if (*s == ':' && *++s != ':') return 0;

if (!MultiByteToWideChar(CP_UTF8, 0, hostname, -1, wName, countof(wName)))
return 0;
for (i = 0; ; i++) {
if (s[0] == ':' && brk < 0) {
brk = i;
if (!*++s) break;
continue;
}
for (n = j = 0; j < 4 && (d = hexval(s[j])) >= 0; j++)
n = n * 16 + d;
if (j == 0) return 0;
if (!s[j] && (brk >= 0 || i == 7)) break;
if (i == 7) return 0;
if (s[j] != ':') {
if (s[j] != '.' || (i < 6 && brk < 0)) return 0;
need_v4 = 1;
i++;
break;
}
s += j + 1;
}

return (WSAStringToAddressW(wName, AF_INET, NULL, (struct sockaddr *)&addr, &size) != SOCKET_ERROR) |
(WSAStringToAddressW(wName, AF_INET6, NULL, (struct sockaddr *)&addr6, &size6) != SOCKET_ERROR);
#else
struct in_addr addr;
struct in6_addr addr6;
if (need_v4 && !is_ip4(s)) return 0;
return 1;
}

return inet_pton(AF_INET, hostname, &addr) || inet_pton(AF_INET6, hostname, &addr6);
#endif
/* return whether hostname is an IP address or not */
static int isip(const char *hostname)
{
return is_ip4(hostname) || is_ip6(hostname);
}

/**
Expand Down Expand Up @@ -1758,7 +1805,7 @@ psl_error_t psl_str_to_utf8lower(const char *str, const char *encoding, const ch
if (lower) {
char *p, *tmp;

if (!(tmp = strdup(str)))
if (!(tmp = psl_strdup(str)))
return PSL_ERR_NO_MEM;

*lower = tmp;
Expand Down Expand Up @@ -1816,7 +1863,7 @@ psl_error_t psl_str_to_utf8lower(const char *str, const char *encoding, const ch
if (U_SUCCESS(status)) {
ret = PSL_SUCCESS;
if (lower) {
char *tmp = strdup(utf8_lower);
char *tmp = psl_strdup(utf8_lower);

if (tmp)
*lower = tmp;
Expand Down
16 changes: 0 additions & 16 deletions tests/test-is-cookie-domain-acceptable.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@
# include <config.h>
#endif

#ifdef _WIN32
# include <winsock2.h> // WSAStartup, WSACleanup
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -111,18 +107,6 @@ static void test_psl(void)

int main(int argc, const char * const *argv)
{
#ifdef _WIN32
WSADATA wsa_data;
int err;

if ((err = WSAStartup(MAKEWORD(2,2), &wsa_data))) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}

atexit((void (__cdecl*)(void)) WSACleanup);
#endif

/* if VALGRIND testing is enabled, we have to call ourselves with valgrind checking */
if (argc == 1) {
const char *valgrind = getenv("TESTS_VALGRIND");
Expand Down
Loading
Loading