dbus: Deal with undefined behavior with va_args.
authorRyan C. Gordon <icculus@icculus.org>
Fri, 13 Jul 2018 17:53:24 -0400
changeset 12062d31364f5afab
parent 12061 d7cb1131aada
child 12063 5b6f649b6488
dbus: Deal with undefined behavior with va_args.

Parse out a copy of the varargs ourselves to get to the reply portion, since
the original passed to D-Bus might modify or not modify the caller's copy,
depending on system ABI.
src/core/linux/SDL_dbus.c
     1.1 --- a/src/core/linux/SDL_dbus.c	Fri Jul 13 12:55:50 2018 -0700
     1.2 +++ b/src/core/linux/SDL_dbus.c	Fri Jul 13 17:53:24 2018 -0400
     1.3 @@ -173,17 +173,29 @@
     1.4      if (conn) {
     1.5          DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method);
     1.6          if (msg) {
     1.7 -            int firstarg = va_arg(ap, int);
     1.8 +            int firstarg;
     1.9 +            va_list ap_reply;
    1.10 +            va_copy(ap_reply, ap);  /* copy the arg list so we don't compete with D-Bus for it */
    1.11 +            firstarg = va_arg(ap, int);
    1.12              if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) {
    1.13                  DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
    1.14                  if (reply) {
    1.15 -                    firstarg = va_arg(ap, int);
    1.16 -                    if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_get_args_valist(reply, NULL, firstarg, ap)) {
    1.17 +                    /* skip any input args, get to output args. */
    1.18 +                    while ((firstarg = va_arg(ap_reply, int)) != DBUS_TYPE_INVALID) {
    1.19 +                        /* we assume D-Bus already validated all this. */
    1.20 +                        { void *dumpptr = va_arg(ap_reply, void*); (void) dumpptr; }
    1.21 +                        if (firstarg == DBUS_TYPE_ARRAY) {
    1.22 +                            { const int dumpint = va_arg(ap_reply, int); (void) dumpint; }
    1.23 +                        }
    1.24 +                    }
    1.25 +                    firstarg = va_arg(ap_reply, int);
    1.26 +                    if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_get_args_valist(reply, NULL, firstarg, ap_reply)) {
    1.27                          retval = SDL_TRUE;
    1.28                      }
    1.29                      dbus.message_unref(reply);
    1.30                  }
    1.31              }
    1.32 +            va_end(ap_reply);
    1.33              dbus.message_unref(msg);
    1.34          }
    1.35      }