1 /* 2 * Permission is hereby granted, free of charge, to any person obtaining 3 * a copy of this software and associated documentation files (the 4 * "Software"), to deal in the Software without restriction, including 5 * without limitation the rights to use, copy, modify, merge, publish, 6 * distribute, sublicense, and/or sell copies of the Software, and to 7 * permit persons to whom the Software is furnished to do so, subject to 8 * the following conditions: 9 * 10 * The above copyright notice and this permission notice (including the 11 * next paragraph) shall be included in all copies or substantial 12 * portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 18 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 */ 23 24 #include <stdlib.h> 25 #include <assert.h> 26 #include <errno.h> 27 #include <string.h> 28 #include <stdio.h> 29 #include <sys/un.h> 30 #include <unistd.h> 31 32 #include "wayland-client.h" 33 #include "wayland-server.h" 34 #include "test-runner.h" 35 36 /* Paths longer than what the .sun_path array can contain must be rejected. 37 * This is a hard limitation of assigning a name to AF_UNIX/AF_LOCAL sockets. 38 * See `man 7 unix`. 39 */ 40 41 static const struct sockaddr_un example_sockaddr_un; 42 43 #define TOO_LONG (1 + sizeof example_sockaddr_un.sun_path) 44 45 /* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */ 46 static const char * 47 require_xdg_runtime_dir(void) 48 { 49 char *val = getenv("XDG_RUNTIME_DIR"); 50 assert(val && "set $XDG_RUNTIME_DIR to run this test"); 51 52 return val; 53 } 54 55 TEST(socket_path_overflow_client_connect) 56 { 57 char path[TOO_LONG]; 58 struct wl_display *d; 59 60 require_xdg_runtime_dir(); 61 62 memset(path, 'a', sizeof path); 63 path[sizeof path - 1] = '\0'; 64 65 d = wl_display_connect(path); 66 assert(d == NULL); 67 assert(errno == ENAMETOOLONG); 68 } 69 70 TEST(socket_path_overflow_server_create) 71 { 72 char path[TOO_LONG]; 73 struct wl_display *d; 74 int ret; 75 76 require_xdg_runtime_dir(); 77 78 memset(path, 'a', sizeof path); 79 path[sizeof path - 1] = '\0'; 80 81 d = wl_display_create(); 82 assert(d != NULL); 83 84 ret = wl_display_add_socket(d, path); 85 assert(ret < 0); 86 assert(errno == ENAMETOOLONG); 87 88 wl_display_destroy(d); 89 } 90 91 TEST(add_existing_socket) 92 { 93 char path[sizeof example_sockaddr_un.sun_path]; 94 const char *name = "wayland-test-0"; 95 const char *xdg_runtime_dir; 96 struct wl_display *d; 97 int ret; 98 size_t len; 99 100 xdg_runtime_dir = require_xdg_runtime_dir(); 101 102 d = wl_display_create(); 103 assert(d != NULL); 104 105 /* this one should be OK */ 106 ret = wl_display_add_socket(d, name); 107 assert(ret == 0); 108 109 /* this one should fail */ 110 ret = wl_display_add_socket(d, name); 111 assert(ret < 0); 112 113 /* the original socket should still exist. 114 * this was a bug introduced in e2c0d47b0c77f18cd90e9c6eabb358c4d89681c8 */ 115 len = snprintf(path, sizeof example_sockaddr_un.sun_path, "%s/%s", 116 xdg_runtime_dir, name); 117 assert(len < sizeof example_sockaddr_un.sun_path 118 && "Bug in test. Path too long"); 119 120 assert(access(path, F_OK) != -1); 121 122 /* the original socket should still exist */ 123 ret = wl_display_add_socket(d, name); 124 assert(ret < 0); 125 126 wl_display_destroy(d); 127 } 128 129 TEST(add_socket_auto) 130 { 131 /* the number of auto sockets is currently 32, 132 * set in wayland-server.c. 133 */ 134 const int MAX_SOCKETS = 32; 135 136 char path[sizeof example_sockaddr_un.sun_path]; 137 const char *name; 138 const char *xdg_runtime_dir; 139 struct wl_display *d; 140 int i; 141 size_t len; 142 143 xdg_runtime_dir = require_xdg_runtime_dir(); 144 145 d = wl_display_create(); 146 assert(d != NULL); 147 148 for (i = 0; i <= MAX_SOCKETS; ++i) { 149 name = wl_display_add_socket_auto(d); 150 assert(name != NULL); 151 152 len = snprintf(path, sizeof example_sockaddr_un.sun_path, 153 "%s/%s", xdg_runtime_dir, name); 154 assert(len < sizeof example_sockaddr_un.sun_path 155 && "Bug in test. Path too long"); 156 157 /* was the socket created correctly? */ 158 assert(access(path, F_OK) != -1); 159 160 /* is the name sequential? */ 161 len = snprintf(path, sizeof example_sockaddr_un.sun_path, 162 "wayland-%d", i); 163 assert(strcmp(name, path) == 0); 164 } 165 166 /* next addition should return NULL */ 167 name = wl_display_add_socket_auto(d); 168 assert(name == NULL); 169 170 /* check if the socket was not deleted the last time */ 171 name = wl_display_add_socket_auto(d); 172 assert(name == NULL); 173 174 wl_display_destroy(d); 175 } 176