From 3618556a95957f82f6fd853af239eb8ce9fa689b Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Thu, 14 Jun 2018 13:25:57 +0900 Subject: struct sockaddr_un can be shorter than struct sockaddr. ref: https://github.com/iij/mruby-socket/issues/45 --- mrbgems/mruby-socket/src/socket.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'mrbgems/mruby-socket/src') diff --git a/mrbgems/mruby-socket/src/socket.c b/mrbgems/mruby-socket/src/socket.c index 037400077..5a8db93d7 100644 --- a/mrbgems/mruby-socket/src/socket.c +++ b/mrbgems/mruby-socket/src/socket.c @@ -664,19 +664,15 @@ mrb_socket_listen(mrb_state *mrb, mrb_value klass) static mrb_value mrb_socket_sockaddr_family(mrb_state *mrb, mrb_value klass) { - mrb_value sa; + const struct sockaddr *sa; + mrb_value str; - mrb_get_args(mrb, "S", &sa); -#ifdef __linux__ - if ((size_t)RSTRING_LEN(sa) < offsetof(struct sockaddr, sa_family) + sizeof(sa_family_t)) { - mrb_raisef(mrb, E_SOCKET_ERROR, "invalid sockaddr (too short)"); - } -#else - if ((size_t)RSTRING_LEN(sa) < sizeof(struct sockaddr)) { + mrb_get_args(mrb, "S", &str); + if ((size_t)RSTRING_LEN(str) < offsetof(struct sockaddr, sa_family) + sizeof(sa_family_t)) { mrb_raisef(mrb, E_SOCKET_ERROR, "invalid sockaddr (too short)"); } -#endif - return mrb_fixnum_value(((struct sockaddr *)RSTRING_PTR(sa))->sa_family); + sa = (const struct sockaddr *)RSTRING_PTR(str); + return mrb_fixnum_value(sa->sa_family); } static mrb_value -- cgit v1.2.3 From 5013d2b20f85819f78c5b5bc4f2f3b8cfc17d89f Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Thu, 14 Jun 2018 13:28:32 +0900 Subject: struct sockaddr_un can be truncated. When we have "struct sockaddr_un *s_un", we could not assume *s_un points to a memory region which size is at least sizeof(*s_un). Even worse, it may be shorter than sizeof(struct sockaddr) on some systems. --- mrbgems/mruby-socket/src/socket.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-socket/src') diff --git a/mrbgems/mruby-socket/src/socket.c b/mrbgems/mruby-socket/src/socket.c index 5a8db93d7..33c8d4455 100644 --- a/mrbgems/mruby-socket/src/socket.c +++ b/mrbgems/mruby-socket/src/socket.c @@ -214,7 +214,11 @@ mrb_addrinfo_unix_path(mrb_state *mrb, mrb_value self) sastr = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@sockaddr")); if (((struct sockaddr *)RSTRING_PTR(sastr))->sa_family != AF_UNIX) mrb_raise(mrb, E_SOCKET_ERROR, "need AF_UNIX address"); - return mrb_str_new_cstr(mrb, ((struct sockaddr_un *)RSTRING_PTR(sastr))->sun_path); + if (RSTRING_LEN(sastr) < offsetof(struct sockaddr_un, sun_path) + 1) { + return mrb_str_new(mrb, "", 0); + } else { + return mrb_str_new_cstr(mrb, ((struct sockaddr_un *)RSTRING_PTR(sastr))->sun_path); + } } #endif -- cgit v1.2.3 From 2eeac910988d9fa4b4e0f19992e8ce3be1d768e9 Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Thu, 14 Jun 2018 13:36:01 +0900 Subject: set sockaddr_un.sun_len on the systems that have sockaddr.sa_len. If your system has sa_len but is not BSD-derived, define HAVE_SA_LEN=1 on mrbgem.rake or build_config.rb. --- mrbgems/mruby-socket/mrbgem.rake | 1 + mrbgems/mruby-socket/src/socket.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) (limited to 'mrbgems/mruby-socket/src') diff --git a/mrbgems/mruby-socket/mrbgem.rake b/mrbgems/mruby-socket/mrbgem.rake index 8096815eb..b0894e095 100644 --- a/mrbgems/mruby-socket/mrbgem.rake +++ b/mrbgems/mruby-socket/mrbgem.rake @@ -4,6 +4,7 @@ MRuby::Gem::Specification.new('mruby-socket') do |spec| spec.summary = 'standard socket class' spec.cc.include_paths << "#{build.root}/src" + #spec.cc.defines << "HAVE_SA_LEN=0" # If Windows, use winsock if ( /mswin|mingw|win32/ =~ RUBY_PLATFORM ) then diff --git a/mrbgems/mruby-socket/src/socket.c b/mrbgems/mruby-socket/src/socket.c index 33c8d4455..951bece75 100644 --- a/mrbgems/mruby-socket/src/socket.c +++ b/mrbgems/mruby-socket/src/socket.c @@ -19,6 +19,7 @@ #else #include #include + #include #include #include #include @@ -42,6 +43,14 @@ #include "mruby/ext/io.h" +#if !defined(HAVE_SA_LEN) +#if (defined(BSD) && (BSD >= 199006)) +#define HAVE_SA_LEN 1 +#else +#define HAVE_SA_LEN 0 +#endif +#endif + #define E_SOCKET_ERROR (mrb_class_get(mrb, "SocketError")) #if !defined(mrb_cptr) @@ -695,6 +704,9 @@ mrb_socket_sockaddr_un(mrb_state *mrb, mrb_value klass) } s = mrb_str_buf_new(mrb, sizeof(struct sockaddr_un)); sunp = (struct sockaddr_un *)RSTRING_PTR(s); +#if HAVE_SA_LEN + sunp->sun_len = sizeof(struct sockaddr_un); +#endif sunp->sun_family = AF_UNIX; memcpy(sunp->sun_path, RSTRING_PTR(path), RSTRING_LEN(path)); sunp->sun_path[RSTRING_LEN(path)] = '\0'; -- cgit v1.2.3 From af8020e7fd6e85672ce41698469f4bacf1f424c2 Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Thu, 14 Jun 2018 13:52:37 +0900 Subject: sa_family_t is not defined on windows. --- mrbgems/mruby-socket/src/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-socket/src') diff --git a/mrbgems/mruby-socket/src/socket.c b/mrbgems/mruby-socket/src/socket.c index 951bece75..89c31c767 100644 --- a/mrbgems/mruby-socket/src/socket.c +++ b/mrbgems/mruby-socket/src/socket.c @@ -681,7 +681,7 @@ mrb_socket_sockaddr_family(mrb_state *mrb, mrb_value klass) mrb_value str; mrb_get_args(mrb, "S", &str); - if ((size_t)RSTRING_LEN(str) < offsetof(struct sockaddr, sa_family) + sizeof(sa_family_t)) { + if ((size_t)RSTRING_LEN(str) < offsetof(struct sockaddr, sa_family) + sizeof(sa->sa_family)) { mrb_raisef(mrb, E_SOCKET_ERROR, "invalid sockaddr (too short)"); } sa = (const struct sockaddr *)RSTRING_PTR(str); -- cgit v1.2.3