]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Add memcpy_safe
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 2 Feb 2016 02:57:41 +0000 (21:57 -0500)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 11 Feb 2016 18:07:02 +0000 (13:07 -0500)
ISO/IEC 9899:1999 §7.21.1/2 says:
Where an argument declared as size_t n specifies the length of the array
for a function, n can have the value zero on a call to that
function. Unless explicitly stated otherwise in the description of a
particular function in this subclause, pointer arguments on such a call
shall still have valid values, as described in 7.1.4.

In base64_append_width memcpy was called as memcpy(x, NULL, 0).  GCC 4.9
started making use of this and assumes This worked fine under -O0, but
does something strange under -O3.

This patch fixes a bug in base64_append_width(), fixes a possible bug in
journal_file_append_entry_internal(), and makes use of the new function
to simplify the code in other places.

12 files changed:
src/basic/hexdecoct.c
src/basic/util.h
src/journal/journal-file.c
src/libsystemd-network/dhcp-option.c
src/libsystemd-network/dhcp6-option.c
src/libsystemd-network/test-dhcp-option.c
src/libsystemd/sd-bus/bus-control.c
src/libsystemd/sd-bus/bus-message.c
src/libsystemd/sd-bus/bus-socket.c
src/libsystemd/sd-resolve/sd-resolve.c
src/nspawn/nspawn.c
src/resolve/resolved-dns-packet.c

index f30e028f45b51baabf152a0fe6112b0bec625c44..cbd97a1b6925ea13bf6d5a399e34b77437274b2e 100644 (file)
@@ -27,6 +27,7 @@
 #include "alloc-util.h"
 #include "hexdecoct.h"
 #include "macro.h"
+#include "util.h"
 
 char octchar(int x) {
         return '0' + (x & 7);
@@ -574,7 +575,7 @@ static int base64_append_width(char **prefix, int plen,
         if (!t)
                 return -ENOMEM;
 
-        memcpy(t + plen, sep, slen);
+        memcpy_safe(t + plen, sep, slen);
 
         for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
                 int act = MIN(width, avail);
index 76a06822b747056a11f5ef0be85f41820139e522..b7bad762121601f0839ea538f4db6db8dbacf3fa 100644 (file)
@@ -104,6 +104,16 @@ static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_
         qsort(base, nmemb, size, compar);
 }
 
+/**
+ * Normal memcpy requires src to be nonnull. We do nothing if n is 0.
+ */
+static inline void memcpy_safe(void *dst, const void *src, size_t n) {
+        if (n == 0)
+                return;
+        assert(src);
+        memcpy(dst, src, n);
+}
+
 int on_ac_power(void);
 
 #define memzero(x,l) (memset((x), 0, (l)))
index 2973176c8de0b29b45dbaa3197d06a4624410c11..da8039712f49262084d460e506f3596b075a3dfb 100644 (file)
@@ -1110,8 +1110,8 @@ static int journal_file_append_data(
         }
 #endif
 
-        if (compression == 0 && size > 0)
-                memcpy(o->data.payload, data, size);
+        if (compression == 0)
+                memcpy_safe(o->data.payload, data, size);
 
         r = journal_file_link_data(f, o, p, hash);
         if (r < 0)
@@ -1373,7 +1373,7 @@ static int journal_file_append_entry_internal(
                 return r;
 
         o->entry.seqnum = htole64(journal_file_entry_seqnum(f, seqnum));
-        memcpy(o->entry.items, items, n_items * sizeof(EntryItem));
+        memcpy_safe(o->entry.items, items, n_items * sizeof(EntryItem));
         o->entry.realtime = htole64(ts->realtime);
         o->entry.monotonic = htole64(ts->monotonic);
         o->entry.xor_hash = htole64(xor_hash);
index 9f0d96e57dd858a8fd1435a7caafe9ebe0ea00b6..3ceb70f07e2bf1b9c5d07a0098979664057493f0 100644 (file)
@@ -56,12 +56,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
                 options[*offset] = code;
                 options[*offset + 1] = optlen;
 
-                if (optlen) {
-                        assert(optval);
-
-                        memcpy(&options[*offset + 2], optval, optlen);
-                }
-
+                memcpy_safe(&options[*offset + 2], optval, optlen);
                 *offset += optlen + 2;
 
                 break;
index 60508518588f60f8797eddcd391804fda3d5879c..e858e14d9723acdd8a8887c61a51df908328b7bd 100644 (file)
@@ -73,8 +73,7 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
         if (r < 0)
                 return r;
 
-        if (optval)
-                memcpy(*buf, optval, optlen);
+        memcpy_safe(*buf, optval, optlen);
 
         *buf += optlen;
         *buflen -= optlen;
index 7b80a5bd904e4b9f9690b21770df55f6b8ef5ab3..45f4e0b5f55b71912dc45c474a7abe4251a42a47 100644 (file)
@@ -112,14 +112,9 @@ static DHCPMessage *create_message(uint8_t *options, uint16_t optlen,
         message = malloc0(len);
         assert_se(message);
 
-        if (options && optlen)
-                memcpy(&message->options, options, optlen);
-
-        if (file && filelen <= 128)
-                memcpy(&message->file, file, filelen);
-
-        if (sname && snamelen <= 64)
-                memcpy(&message->sname, sname, snamelen);
+        memcpy_safe(&message->options, options, optlen);
+        memcpy_safe(&message->file, file, filelen);
+        memcpy_safe(&message->sname, sname, snamelen);
 
         return message;
 }
index ff628cfe72e0611c239cf93b8ca716cf2dcc382a..00de2a95dab63c3355a0d632d81251e438041f64 100644 (file)
@@ -1133,8 +1133,7 @@ static int add_name_change_match(sd_bus *bus,
                 item->name_change.old_id.id = old_owner_id;
                 item->name_change.new_id.id = new_owner_id;
 
-                if (name)
-                        memcpy(item->name_change.name, name, l);
+                memcpy_safe(item->name_change.name, name, l);
 
                 /* If the old name is unset or empty, then
                  * this can match against added names */
index e939359338c8103bccecf462492e4ad72ce25a9c..6fd00013591f01d3b6c4423eb99144845622f14b 100644 (file)
@@ -2633,8 +2633,7 @@ _public_ int sd_bus_message_append_array(
         if (r < 0)
                 return r;
 
-        if (size > 0)
-                memcpy(p, ptr, size);
+        memcpy_safe(p, ptr, size);
 
         return 0;
 }
index 1df571ac926da415280cf13d49f35bdd90e283f0..4f9971923122eff8d6bf673d5e7122829fc4cd24 100644 (file)
@@ -352,7 +352,7 @@ static int bus_socket_auth_write(sd_bus *b, const char *t) {
         if (!p)
                 return -ENOMEM;
 
-        memcpy(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len);
+        memcpy_safe(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len);
         memcpy(p + b->auth_iovec[0].iov_len, t, l);
 
         b->auth_iovec[0].iov_base = p;
@@ -789,7 +789,7 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
 
         n = m->n_iovec * sizeof(struct iovec);
         iov = alloca(n);
-        memcpy(iov, m->iovec, n);
+        memcpy_safe(iov, m->iovec, n);
 
         j = 0;
         iovec_advance(iov, &j, *idx);
@@ -1000,7 +1000,7 @@ int bus_socket_read_message(sd_bus *bus) {
                                         return -ENOMEM;
                                 }
 
-                                memcpy(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int));
+                                memcpy_safe(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int));
                                 bus->fds = f;
                                 bus->n_fds += n;
                         } else
index d6e6f396d4331695aa8b742cbef4c31f4101a23d..c3489cb02f52b15af63bbf07d013ab157f4bc747 100644 (file)
@@ -219,9 +219,8 @@ static void *serialize_addrinfo(void *p, const struct addrinfo *ai, size_t *leng
 
         memcpy((uint8_t*) p, &s, sizeof(AddrInfoSerialization));
         memcpy((uint8_t*) p + sizeof(AddrInfoSerialization), ai->ai_addr, ai->ai_addrlen);
-
-        if (ai->ai_canonname)
-                memcpy((char*) p + sizeof(AddrInfoSerialization) + ai->ai_addrlen, ai->ai_canonname, cnl);
+        memcpy_safe((char*) p + sizeof(AddrInfoSerialization) + ai->ai_addrlen,
+                    ai->ai_canonname, cnl);
 
         *length += l;
         return (uint8_t*) p + l;
index 9dd4c051b2a40873b53785ebd39f0be12a121fae..1c010b3b84d63fbd209db854be28b7882baa8a42 100644 (file)
@@ -2580,12 +2580,10 @@ static int inner_child(
 
                 /* Automatically search for the init system */
 
-                m = 1 + strv_length(arg_parameters);
-                a = newa(char*, m + 1);
-                if (strv_isempty(arg_parameters))
-                        a[1] = NULL;
-                else
-                        memcpy(a + 1, arg_parameters, m * sizeof(char*));
+                m = strv_length(arg_parameters);
+                a = newa(char*, m + 2);
+                memcpy_safe(a + 1, arg_parameters, m * sizeof(char*));
+                a[1 + m] = NULL;
 
                 a[0] = (char*) "/usr/lib/systemd/systemd";
                 execve(a[0], a, env_use);
index 5cbe20832f3c70d92c5ffaa6091bf6f27850be34..abb9725b737087e041d830b37efeb1db79fbfc92 100644 (file)
@@ -433,8 +433,7 @@ int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_
 
         ((uint8_t*) d)[0] = (uint8_t) size;
 
-        if (size > 0)
-                memcpy(((uint8_t*) d) + 1, s, size);
+        memcpy_safe(((uint8_t*) d) + 1, s, size);
 
         return 0;
 }