Andrew Geissler | 9aee500 | 2022-03-30 16:27:02 +0000 | [diff] [blame^] | 1 | From e429db7e8c266045aee25e153fb2308bd61fe233 Mon Sep 17 00:00:00 2001 |
| 2 | From: Julian Bouzas <julian.bouzas@collabora.com> |
| 3 | Date: Wed, 9 Feb 2022 07:59:59 -0500 |
| 4 | Subject: [PATCH] spa-json: fix va_list APIs for different architectures |
| 5 | |
| 6 | The va_list type might not always be a pointer in some architectures, so we |
| 7 | cannot guarantee it will be modified after using it for a second time in another |
| 8 | function. This fixes the issue by using macros so args does not get copied, and |
| 9 | always gets modified when using it more than once. |
| 10 | |
| 11 | Upstream-Status: Backport [https://gitlab.freedesktop.org/pipewire/wireplumber/-/commit/e429db7e8c266045aee25e153fb2308bd61fe233] |
| 12 | |
| 13 | Signed-off-by: Peter Bergin <peter@berginkonsult.se> |
| 14 | |
| 15 | --- |
| 16 | lib/wp/spa-json.c | 156 ++++++++++++++++++++++++---------------------- |
| 17 | 1 file changed, 80 insertions(+), 76 deletions(-) |
| 18 | |
| 19 | diff --git a/lib/wp/spa-json.c b/lib/wp/spa-json.c |
| 20 | index f14f395..c5e59a3 100644 |
| 21 | --- a/lib/wp/spa-json.c |
| 22 | +++ b/lib/wp/spa-json.c |
| 23 | @@ -363,33 +363,33 @@ wp_spa_json_new_string (const gchar *value) |
| 24 | wp_spa_json_builder_new_formatted ("\"%s\"", value)); |
| 25 | } |
| 26 | |
| 27 | -static void |
| 28 | -wp_spa_json_builder_add_value (WpSpaJsonBuilder *self, const gchar *fmt, |
| 29 | - va_list args) |
| 30 | -{ |
| 31 | - switch (*fmt) { |
| 32 | - case 'n': |
| 33 | - wp_spa_json_builder_add_null (self); |
| 34 | - break; |
| 35 | - case 'b': |
| 36 | - wp_spa_json_builder_add_boolean (self, va_arg(args, gboolean)); |
| 37 | - break; |
| 38 | - case 'i': |
| 39 | - wp_spa_json_builder_add_int (self, va_arg(args, gint)); |
| 40 | - break; |
| 41 | - case 'f': |
| 42 | - wp_spa_json_builder_add_float (self, (float)va_arg(args, double)); |
| 43 | - break; |
| 44 | - case 's': |
| 45 | - wp_spa_json_builder_add_string (self, va_arg(args, const gchar *)); |
| 46 | - break; |
| 47 | - case 'J': |
| 48 | - wp_spa_json_builder_add_json (self, va_arg(args, WpSpaJson *)); |
| 49 | - break; |
| 50 | - default: |
| 51 | - return; |
| 52 | - } |
| 53 | -} |
| 54 | +/* Args is not a pointer in some architectures, so this needs to be a macro to |
| 55 | + * avoid args being copied */ |
| 56 | +#define wp_spa_json_builder_add_value(self,fmt,args) \ |
| 57 | +do { \ |
| 58 | + switch (*fmt) { \ |
| 59 | + case 'n': \ |
| 60 | + wp_spa_json_builder_add_null (self); \ |
| 61 | + break; \ |
| 62 | + case 'b': \ |
| 63 | + wp_spa_json_builder_add_boolean (self, va_arg(args, gboolean)); \ |
| 64 | + break; \ |
| 65 | + case 'i': \ |
| 66 | + wp_spa_json_builder_add_int (self, va_arg(args, gint)); \ |
| 67 | + break; \ |
| 68 | + case 'f': \ |
| 69 | + wp_spa_json_builder_add_float (self, (float)va_arg(args, double)); \ |
| 70 | + break; \ |
| 71 | + case 's': \ |
| 72 | + wp_spa_json_builder_add_string (self, va_arg(args, const gchar *)); \ |
| 73 | + break; \ |
| 74 | + case 'J': \ |
| 75 | + wp_spa_json_builder_add_json (self, va_arg(args, WpSpaJson *)); \ |
| 76 | + break; \ |
| 77 | + default: \ |
| 78 | + break; \ |
| 79 | + } \ |
| 80 | +} while(false) |
| 81 | |
| 82 | /*! |
| 83 | * \brief Creates a spa json of type array |
| 84 | @@ -724,48 +724,46 @@ wp_spa_json_parse_object_valist (WpSpaJson *self, va_list args) |
| 85 | return res; |
| 86 | } |
| 87 | |
| 88 | -static gboolean |
| 89 | -wp_spa_json_parse_value (const gchar *data, int len, const gchar *fmt, |
| 90 | - va_list args) |
| 91 | -{ |
| 92 | - switch (*fmt) { |
| 93 | - case 'n': |
| 94 | - if (!spa_json_is_null (data, len)) |
| 95 | - return FALSE; |
| 96 | - break; |
| 97 | - case 'b': |
| 98 | - if (!wp_spa_json_parse_boolean_internal (data, len, |
| 99 | - va_arg(args, gboolean *))) |
| 100 | - return FALSE; |
| 101 | - break; |
| 102 | - case 'i': |
| 103 | - if (spa_json_parse_int (data, len, va_arg(args, gint *)) < 0) |
| 104 | - return FALSE; |
| 105 | - break; |
| 106 | - case 'f': |
| 107 | - if (spa_json_parse_float (data, len, |
| 108 | - (float *)va_arg(args, double *)) < 0) |
| 109 | - return FALSE; |
| 110 | - break; |
| 111 | - case 's': { |
| 112 | - gchar *str = wp_spa_json_parse_string_internal (data, len); |
| 113 | - if (!str) |
| 114 | - return FALSE; |
| 115 | - *va_arg(args, gchar **) = str; |
| 116 | - break; |
| 117 | - } |
| 118 | - case 'J': { |
| 119 | - WpSpaJson *j = wp_spa_json_new (data, len); |
| 120 | - if (!j) |
| 121 | - return FALSE; |
| 122 | - *va_arg(args, WpSpaJson **) = j; |
| 123 | - break; |
| 124 | - } |
| 125 | - default: |
| 126 | - return FALSE; |
| 127 | - } |
| 128 | - return TRUE; |
| 129 | -} |
| 130 | +/* Args is not a pointer in some architectures, so this needs to be a macro to |
| 131 | + * avoid args being copied */ |
| 132 | +#define wp_spa_json_parse_value(data,len,fmt,args) \ |
| 133 | +do { \ |
| 134 | + switch (*fmt) { \ |
| 135 | + case 'n': \ |
| 136 | + if (!spa_json_is_null (data, len)) \ |
| 137 | + return FALSE; \ |
| 138 | + break; \ |
| 139 | + case 'b': \ |
| 140 | + if (!wp_spa_json_parse_boolean_internal (data, len, \ |
| 141 | + va_arg(args, gboolean *))) \ |
| 142 | + return FALSE; \ |
| 143 | + break; \ |
| 144 | + case 'i': \ |
| 145 | + if (spa_json_parse_int (data, len, va_arg(args, gint *)) < 0) \ |
| 146 | + return FALSE; \ |
| 147 | + break; \ |
| 148 | + case 'f': \ |
| 149 | + if (spa_json_parse_float (data, len, va_arg(args, float *)) < 0) \ |
| 150 | + return FALSE; \ |
| 151 | + break; \ |
| 152 | + case 's': { \ |
| 153 | + gchar *str = wp_spa_json_parse_string_internal (data, len); \ |
| 154 | + if (!str) \ |
| 155 | + return FALSE; \ |
| 156 | + *va_arg(args, gchar **) = str; \ |
| 157 | + break; \ |
| 158 | + } \ |
| 159 | + case 'J': { \ |
| 160 | + WpSpaJson *j = wp_spa_json_new (data, len); \ |
| 161 | + if (!j) \ |
| 162 | + return FALSE; \ |
| 163 | + *va_arg(args, WpSpaJson **) = j; \ |
| 164 | + break; \ |
| 165 | + } \ |
| 166 | + default: \ |
| 167 | + return FALSE; \ |
| 168 | + } \ |
| 169 | +} while(false) |
| 170 | |
| 171 | /*! |
| 172 | * \brief Parses the object property values of a spa json object |
| 173 | @@ -827,8 +825,7 @@ wp_spa_json_object_get_valist (WpSpaJson *self, va_list args) |
| 174 | value = g_value_get_boxed (&item); |
| 175 | |
| 176 | if (g_strcmp0 (key_str, lookup_key) == 0) { |
| 177 | - if (!wp_spa_json_parse_value (value->data, value->size, lookup_fmt, args)) |
| 178 | - return FALSE; |
| 179 | + wp_spa_json_parse_value (value->data, value->size, lookup_fmt, args); |
| 180 | lookup_key = va_arg(args, const gchar *); |
| 181 | if (!lookup_key) |
| 182 | return TRUE; |
| 183 | @@ -1366,9 +1363,12 @@ gboolean |
| 184 | wp_spa_json_parser_get_value (WpSpaJsonParser *self, const gchar *fmt, |
| 185 | va_list args) |
| 186 | { |
| 187 | - return wp_spa_json_parser_advance (self) && |
| 188 | - wp_spa_json_parse_value (self->curr.cur, |
| 189 | - self->curr.end - self->curr.cur, fmt, args); |
| 190 | + if (wp_spa_json_parser_advance (self)) { |
| 191 | + wp_spa_json_parse_value (self->curr.cur, self->curr.end - self->curr.cur, |
| 192 | + fmt, args); |
| 193 | + return TRUE; |
| 194 | + } |
| 195 | + return FALSE; |
| 196 | } |
| 197 | |
| 198 | /*! |
| 199 | @@ -1419,9 +1419,13 @@ wp_spa_json_parser_get_valist (WpSpaJsonParser *self, va_list args) |
| 200 | if (!format) |
| 201 | return TRUE; |
| 202 | |
| 203 | - /* parse value */ |
| 204 | - if (!wp_spa_json_parser_get_value (self, format, args)) |
| 205 | + /* advance */ |
| 206 | + if (!wp_spa_json_parser_advance (self)) |
| 207 | return FALSE; |
| 208 | + |
| 209 | + /* parse value */ |
| 210 | + wp_spa_json_parse_value (self->curr.cur, self->curr.end - self->curr.cur, |
| 211 | + format, args); |
| 212 | } while (TRUE); |
| 213 | |
| 214 | return FALSE; |
| 215 | -- |
| 216 | 2.32.0 |
| 217 | |