diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2020-05-20 09:05:17 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2020-05-31 07:05:13 +0200 |
commit | 116a8eadb6adb14c8a4d63ee2f7444c8629df6d0 (patch) | |
tree | 0b86e9d20cc817b71a10e5c296969d31874e7d4c | |
parent | 4d5779d886d06441f94a07449a3ee55f3ee748f3 (diff) | |
download | systemd-116a8eadb6adb14c8a4d63ee2f7444c8629df6d0.tar.gz |
bus-message: fix negative offset with ~empty message
In the linked reproducer, m->fields_size == 0, and we calculate ri == -1, which
of course doesn't end well. Skip the whole calculation if m->fields_size == 0,
and also check that we don't go negative even if it is non-zero.
Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19446 and #15583.
(cherry picked from commit e0c17a7d1bdd197dfb5e24ba527bd281f404f1a9)
-rw-r--r-- | src/libsystemd/sd-bus/bus-message.c | 43 | ||||
-rw-r--r-- | test/fuzz/fuzz-bus-message/oss-fuzz-19446 | bin | 0 -> 17 bytes |
2 files changed, 24 insertions, 19 deletions
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 2348821c7b..a7ec9bb613 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -5201,29 +5201,34 @@ int bus_message_parse_fields(sd_bus_message *m) { * table */ m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p); - /* Pull out the offset table for the fields array */ - sz = bus_gvariant_determine_word_size(m->fields_size, 0); - if (sz > 0) { - size_t framing; - void *q; + /* Pull out the offset table for the fields array, if any */ + if (m->fields_size > 0) { + sz = bus_gvariant_determine_word_size(m->fields_size, 0); + if (sz > 0) { + size_t framing; + void *q; + + if (m->fields_size < sz) + return -EBADMSG; - ri = m->fields_size - sz; - r = message_peek_fields(m, &ri, 1, sz, &q); - if (r < 0) - return r; + ri = m->fields_size - sz; + r = message_peek_fields(m, &ri, 1, sz, &q); + if (r < 0) + return r; - framing = bus_gvariant_read_word_le(q, sz); - if (framing >= m->fields_size - sz) - return -EBADMSG; - if ((m->fields_size - framing) % sz != 0) - return -EBADMSG; + framing = bus_gvariant_read_word_le(q, sz); + if (framing >= m->fields_size - sz) + return -EBADMSG; + if ((m->fields_size - framing) % sz != 0) + return -EBADMSG; - ri = framing; - r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets); - if (r < 0) - return r; + ri = framing; + r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets); + if (r < 0) + return r; - n_offsets = (m->fields_size - framing) / sz; + n_offsets = (m->fields_size - framing) / sz; + } } } else m->user_body_size = m->body_size; diff --git a/test/fuzz/fuzz-bus-message/oss-fuzz-19446 b/test/fuzz/fuzz-bus-message/oss-fuzz-19446 Binary files differnew file mode 100644 index 0000000000..f937ef8c71 --- /dev/null +++ b/test/fuzz/fuzz-bus-message/oss-fuzz-19446 |