1
0
mirror of https://gitlab.gnome.org/GNOME/glib.git synced 2026-10-24 00:49:00 +03:00
Files
glib/gio/tests/socket-address.c
Philip Withnall d60cd821b7 tests: Avoid a ubsan warning about passing NULL to strncmp()
The array data can be `NULL` if its length is zero.

This fixes the following CI failure:
```
322/425 glib:gio / socket-address                                              ERROR            0.08s   killed by signal 6 SIGABRT
――――――――――――――――――――――――――――――――――――― ✀  ―――――――――――――――――――――――――――――――――――――
stderr:
../gio/tests/socket-address.c:201:19: runtime error: null pointer passed as argument 2, which is declared to never be null
/usr/include/string.h:160:33: note: nonnull attribute specified here
    #0 0x000000431715  (/builds/GNOME/glib/_build/gio/tests/socket-address+0x431715) (BuildId: 7c5e418267aa2008af8e77f4d04c31913e26aad7)
    #1 0x7fdabec8c862  (/builds/GNOME/glib/_build/glib/libglib-2.0.so.0+0x28c862) (BuildId: 12f0fded04a8c0437c073a267547f1cb487b1b1d)
    #2 0x7fdabec7e1b2  (/builds/GNOME/glib/_build/glib/libglib-2.0.so.0+0x27e1b2) (BuildId: 12f0fded04a8c0437c073a267547f1cb487b1b1d)
    #3 0x7fdabec7e533  (/builds/GNOME/glib/_build/glib/libglib-2.0.so.0+0x27e533) (BuildId: 12f0fded04a8c0437c073a267547f1cb487b1b1d)
    #4 0x7fdabec7e533  (/builds/GNOME/glib/_build/glib/libglib-2.0.so.0+0x27e533) (BuildId: 12f0fded04a8c0437c073a267547f1cb487b1b1d)
    #5 0x7fdabec7e533  (/builds/GNOME/glib/_build/glib/libglib-2.0.so.0+0x27e533) (BuildId: 12f0fded04a8c0437c073a267547f1cb487b1b1d)
    #6 0x7fdabec7bc89  (/builds/GNOME/glib/_build/glib/libglib-2.0.so.0+0x27bc89) (BuildId: 12f0fded04a8c0437c073a267547f1cb487b1b1d)
    #7 0x7fdabec7b785  (/builds/GNOME/glib/_build/glib/libglib-2.0.so.0+0x27b785) (BuildId: 12f0fded04a8c0437c073a267547f1cb487b1b1d)
    #8 0x00000042de31  (/builds/GNOME/glib/_build/gio/tests/socket-address+0x42de31) (BuildId: 7c5e418267aa2008af8e77f4d04c31913e26aad7)
    #9 0x7fdabd810447  (/lib64/libc.so.6+0x3447) (BuildId: dae6ae6929d69dca842288f5300af5a33d1bdcd7)
    #10 0x7fdabd81050a  (/lib64/libc.so.6+0x350a) (BuildId: dae6ae6929d69dca842288f5300af5a33d1bdcd7)
    #11 0x0000004015a4  (/builds/GNOME/glib/_build/gio/tests/socket-address+0x4015a4) (BuildId: 7c5e418267aa2008af8e77f4d04c31913e26aad7)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../gio/tests/socket-address.c:201:19
```

https://gitlab.gnome.org/GNOME/glib/-/jobs/7120334

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2026-10-06 12:35:19 +01:00

265 lines
9.8 KiB
C

#include <gio/gunixsocketaddress.h>
#include <sys/socket.h>
#include <sys/un.h>
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX G_SIZEOF_MEMBER (struct sockaddr_un, sun_path)
#endif
static void
test_socket_address_native_cornercases (void)
{
GSocketAddress *a;
struct sockaddr_un sun;
struct sockaddr_un too_big[2];
/* no data */
g_assert_null (g_socket_address_new_from_native (NULL, 0));
/* not null-terminated unix path */
memset (&sun, 'a', sizeof (struct sockaddr_un));
sun.sun_family = AF_UNIX;
a = g_socket_address_new_from_native (&sun, sizeof (sun));
g_assert_nonnull (a);
g_assert_true (G_IS_UNIX_SOCKET_ADDRESS (a));
/* ensure this gets null-terminated by the constructor */
g_assert_cmpuint (g_unix_socket_address_get_path_len (G_UNIX_SOCKET_ADDRESS (a)), ==, sizeof (sun.sun_path));
g_object_unref (a);
/* unix path with embedded NULL */
sun.sun_path[4] = 0;
a = g_socket_address_new_from_native (&sun, sizeof (sun));
g_assert_nonnull (a);
g_assert_true (G_IS_UNIX_SOCKET_ADDRESS (a));
g_assert_cmpuint (g_unix_socket_address_get_path_len (G_UNIX_SOCKET_ADDRESS (a)), ==, sizeof (sun.sun_path));
g_object_unref (a);
/* specific test for an error check in g_socket_address_new_from_native() */
g_assert_null (g_socket_address_new_from_native (&sun, G_STRUCT_OFFSET (struct sockaddr_un, sun_path) - 1));
/* not null-terminated unix path */
memset (&too_big, 'b', sizeof (too_big));
too_big[0].sun_family = AF_UNIX;
a = g_socket_address_new_from_native (too_big, sizeof (too_big));
g_assert_nonnull (a);
g_assert_true (G_IS_UNIX_SOCKET_ADDRESS (a));
g_assert_cmpuint (g_unix_socket_address_get_path_len (G_UNIX_SOCKET_ADDRESS (a)), ==, sizeof (sun.sun_path));
g_object_unref (a);
}
static void
test_unix_socket_address_construct (void)
{
GUnixSocketAddress *a;
a = g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS, NULL);
g_assert_cmpint (g_unix_socket_address_get_address_type (a), ==, G_UNIX_SOCKET_ADDRESS_PATH);
g_object_unref (a);
/* Try passing some default values for the arguments explicitly and
* make sure it makes no difference.
*/
a = g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS, "address-type", G_UNIX_SOCKET_ADDRESS_PATH, NULL);
g_assert_cmpint (g_unix_socket_address_get_address_type (a), ==, G_UNIX_SOCKET_ADDRESS_PATH);
g_object_unref (a);
a = g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS, "abstract", FALSE, NULL);
g_assert_cmpint (g_unix_socket_address_get_address_type (a), ==, G_UNIX_SOCKET_ADDRESS_PATH);
g_object_unref (a);
a = g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS,
"abstract", FALSE,
"address-type", G_UNIX_SOCKET_ADDRESS_PATH,
NULL);
g_assert_cmpint (g_unix_socket_address_get_address_type (a), ==, G_UNIX_SOCKET_ADDRESS_PATH);
g_object_unref (a);
a = g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS,
"address-type", G_UNIX_SOCKET_ADDRESS_PATH,
"abstract", FALSE,
NULL);
g_assert_cmpint (g_unix_socket_address_get_address_type (a), ==, G_UNIX_SOCKET_ADDRESS_PATH);
g_object_unref (a);
/* Try explicitly setting abstract to TRUE */
a = g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS,
"abstract", TRUE,
NULL);
g_assert_cmpint (g_unix_socket_address_get_address_type (a), ==, G_UNIX_SOCKET_ADDRESS_ABSTRACT_PADDED);
g_object_unref (a);
/* Try explicitly setting a different kind of address */
a = g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS,
"address-type", G_UNIX_SOCKET_ADDRESS_ANONYMOUS,
NULL);
g_assert_cmpint (g_unix_socket_address_get_address_type (a), ==, G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
g_object_unref (a);
/* Now try explicitly setting a different type of address after
* setting abstract to FALSE.
*/
a = g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS,
"abstract", FALSE,
"address-type", G_UNIX_SOCKET_ADDRESS_ANONYMOUS,
NULL);
g_assert_cmpint (g_unix_socket_address_get_address_type (a), ==, G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
g_object_unref (a);
/* And the other way around */
a = g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS,
"address-type", G_UNIX_SOCKET_ADDRESS_ANONYMOUS,
"abstract", FALSE,
NULL);
g_assert_cmpint (g_unix_socket_address_get_address_type (a), ==, G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
g_object_unref (a);
}
static void
test_unix_socket_address_construct_path (void)
{
struct {
GUnixSocketAddressType address_type;
gsize max_len;
} sizes[] = {
{ G_UNIX_SOCKET_ADDRESS_ANONYMOUS, 0 },
{ G_UNIX_SOCKET_ADDRESS_PATH, UNIX_PATH_MAX },
{ G_UNIX_SOCKET_ADDRESS_ABSTRACT, UNIX_PATH_MAX - 1 },
{ G_UNIX_SOCKET_ADDRESS_ABSTRACT_PADDED, UNIX_PATH_MAX - 1 },
};
gsize lengths[] = { 0, 1, 2, 4, 8, 15, 16, 32, 64, 128, 256,
UNIX_PATH_MAX - 2, UNIX_PATH_MAX - 1, UNIX_PATH_MAX, UNIX_PATH_MAX + 1, UNIX_PATH_MAX + 2 };
GByteArray *array;
GSocketAddress *a[4];
gsize i, j, k, l, path_len[4];
const char *path[4];
array = g_byte_array_new ();
for (i = 0; i < G_N_ELEMENTS (sizes); i++)
{
for (j = 0; j < G_N_ELEMENTS (lengths); j++)
{
g_byte_array_set_size (array, lengths[j]);
for (k = 0; k < G_N_ELEMENTS (lengths); k++)
{
gsize stringlen = lengths[k];
if (stringlen > array->len)
continue;
if (stringlen > 0)
memset (array->data, 'x', stringlen);
if (stringlen < array->len)
memset (array->data + stringlen, 0, array->len - stringlen);
if (stringlen < array->len)
{
a[0] = g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS,
"address-type", sizes[i].address_type,
"path", array->len > 0 ? (char *) array->data : "",
NULL);
a[1] = g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS,
"path", array->len > 0 ? (char *) array->data : "",
"address-type", sizes[i].address_type,
NULL);
}
else
{
a[0] = NULL;
a[1] = NULL;
}
a[2] = g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS,
"address-type", sizes[i].address_type,
"path-as-array", array,
NULL);
a[3] = g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS,
"path-as-array", array,
"address-type", sizes[i].address_type,
NULL);
for (l = 0; l < G_N_ELEMENTS (a); l++)
{
if (a[l] == NULL)
continue;
path[l] = g_unix_socket_address_get_path (G_UNIX_SOCKET_ADDRESS (a[l]));
path_len[l] = g_unix_socket_address_get_path_len (G_UNIX_SOCKET_ADDRESS (a[l]));
if (l < 2)
{
/* used path */
g_assert_cmpuint (path_len[l], ==, MIN (sizes[i].max_len, stringlen));
}
else
{
/* used path-as-array */
g_assert_cmpuint (path_len[l], ==, MIN (sizes[i].max_len, array->len));
}
g_assert_cmpuint (strlen (path[l]), <=, MIN (path_len[l], stringlen));
/* because there's no g_assert_cmpstrn() */
g_assert_cmpint (strncmp (path[l], array->len > 0 ? (char *) array->data : "", path_len[l]), ==, 0);
g_object_unref (a[l]);
}
}
}
}
g_byte_array_unref (array);
}
static void
test_unix_socket_address_to_string (void)
{
GSocketAddress *addr = NULL;
gchar *str = NULL;
/* ADDRESS_PATH. */
addr = g_unix_socket_address_new_with_type ("/some/path", -1,
G_UNIX_SOCKET_ADDRESS_PATH);
str = g_socket_connectable_to_string (G_SOCKET_CONNECTABLE (addr));
g_assert_cmpstr (str, ==, "/some/path");
g_free (str);
g_object_unref (addr);
/* ADDRESS_ANONYMOUS. */
addr = g_unix_socket_address_new_with_type ("", 0,
G_UNIX_SOCKET_ADDRESS_ANONYMOUS);
str = g_socket_connectable_to_string (G_SOCKET_CONNECTABLE (addr));
g_assert_cmpstr (str, ==, "anonymous");
g_free (str);
g_object_unref (addr);
/* ADDRESS_ABSTRACT. */
addr = g_unix_socket_address_new_with_type ("abstract-path\0✋", 17,
G_UNIX_SOCKET_ADDRESS_ABSTRACT);
str = g_socket_connectable_to_string (G_SOCKET_CONNECTABLE (addr));
g_assert_cmpstr (str, ==, "abstract-path\\x00\\xe2\\x9c\\x8b");
g_free (str);
g_object_unref (addr);
/* ADDRESS_ABSTRACT_PADDED. */
addr = g_unix_socket_address_new_with_type ("abstract-path\0✋", 17,
G_UNIX_SOCKET_ADDRESS_ABSTRACT_PADDED);
str = g_socket_connectable_to_string (G_SOCKET_CONNECTABLE (addr));
g_assert_cmpstr (str, ==, "abstract-path\\x00\\xe2\\x9c\\x8b");
g_free (str);
g_object_unref (addr);
}
int
main (int argc,
char **argv)
{
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/socket/address/native/cornercases", test_socket_address_native_cornercases);
g_test_add_func ("/socket/address/unix/construct", test_unix_socket_address_construct);
g_test_add_func ("/socket/address/unix/construct-path", test_unix_socket_address_construct_path);
g_test_add_func ("/socket/address/unix/to-string", test_unix_socket_address_to_string);
return g_test_run ();
}