summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-05-20 09:05:17 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-05-31 07:05:13 +0200
commit116a8eadb6adb14c8a4d63ee2f7444c8629df6d0 (patch)
tree0b86e9d20cc817b71a10e5c296969d31874e7d4c
parent4d5779d886d06441f94a07449a3ee55f3ee748f3 (diff)
downloadsystemd-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.c43
-rw-r--r--test/fuzz/fuzz-bus-message/oss-fuzz-19446bin0 -> 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
new file mode 100644
index 0000000000..f937ef8c71
--- /dev/null
+++ b/test/fuzz/fuzz-bus-message/oss-fuzz-19446
Binary files differ