]>
Commit | Line | Data |
---|---|---|
aa4be26c JP |
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 | lib/wp/spa-json.c | 156 ++++++++++++++++++++++++---------------------- | |
12 | 1 file changed, 80 insertions(+), 76 deletions(-) | |
13 | ||
14 | diff --git a/lib/wp/spa-json.c b/lib/wp/spa-json.c | |
15 | index f14f395d..c5e59a3e 100644 | |
16 | --- a/lib/wp/spa-json.c | |
17 | +++ b/lib/wp/spa-json.c | |
18 | @@ -363,33 +363,33 @@ wp_spa_json_new_string (const gchar *value) | |
19 | wp_spa_json_builder_new_formatted ("\"%s\"", value)); | |
20 | } | |
21 | ||
22 | -static void | |
23 | -wp_spa_json_builder_add_value (WpSpaJsonBuilder *self, const gchar *fmt, | |
24 | - va_list args) | |
25 | -{ | |
26 | - switch (*fmt) { | |
27 | - case 'n': | |
28 | - wp_spa_json_builder_add_null (self); | |
29 | - break; | |
30 | - case 'b': | |
31 | - wp_spa_json_builder_add_boolean (self, va_arg(args, gboolean)); | |
32 | - break; | |
33 | - case 'i': | |
34 | - wp_spa_json_builder_add_int (self, va_arg(args, gint)); | |
35 | - break; | |
36 | - case 'f': | |
37 | - wp_spa_json_builder_add_float (self, (float)va_arg(args, double)); | |
38 | - break; | |
39 | - case 's': | |
40 | - wp_spa_json_builder_add_string (self, va_arg(args, const gchar *)); | |
41 | - break; | |
42 | - case 'J': | |
43 | - wp_spa_json_builder_add_json (self, va_arg(args, WpSpaJson *)); | |
44 | - break; | |
45 | - default: | |
46 | - return; | |
47 | - } | |
48 | -} | |
49 | +/* Args is not a pointer in some architectures, so this needs to be a macro to | |
50 | + * avoid args being copied */ | |
51 | +#define wp_spa_json_builder_add_value(self,fmt,args) \ | |
52 | +do { \ | |
53 | + switch (*fmt) { \ | |
54 | + case 'n': \ | |
55 | + wp_spa_json_builder_add_null (self); \ | |
56 | + break; \ | |
57 | + case 'b': \ | |
58 | + wp_spa_json_builder_add_boolean (self, va_arg(args, gboolean)); \ | |
59 | + break; \ | |
60 | + case 'i': \ | |
61 | + wp_spa_json_builder_add_int (self, va_arg(args, gint)); \ | |
62 | + break; \ | |
63 | + case 'f': \ | |
64 | + wp_spa_json_builder_add_float (self, (float)va_arg(args, double)); \ | |
65 | + break; \ | |
66 | + case 's': \ | |
67 | + wp_spa_json_builder_add_string (self, va_arg(args, const gchar *)); \ | |
68 | + break; \ | |
69 | + case 'J': \ | |
70 | + wp_spa_json_builder_add_json (self, va_arg(args, WpSpaJson *)); \ | |
71 | + break; \ | |
72 | + default: \ | |
73 | + break; \ | |
74 | + } \ | |
75 | +} while(false) | |
76 | ||
77 | /*! | |
78 | * \brief Creates a spa json of type array | |
79 | @@ -724,48 +724,46 @@ wp_spa_json_parse_object_valist (WpSpaJson *self, va_list args) | |
80 | return res; | |
81 | } | |
82 | ||
83 | -static gboolean | |
84 | -wp_spa_json_parse_value (const gchar *data, int len, const gchar *fmt, | |
85 | - va_list args) | |
86 | -{ | |
87 | - switch (*fmt) { | |
88 | - case 'n': | |
89 | - if (!spa_json_is_null (data, len)) | |
90 | - return FALSE; | |
91 | - break; | |
92 | - case 'b': | |
93 | - if (!wp_spa_json_parse_boolean_internal (data, len, | |
94 | - va_arg(args, gboolean *))) | |
95 | - return FALSE; | |
96 | - break; | |
97 | - case 'i': | |
98 | - if (spa_json_parse_int (data, len, va_arg(args, gint *)) < 0) | |
99 | - return FALSE; | |
100 | - break; | |
101 | - case 'f': | |
102 | - if (spa_json_parse_float (data, len, | |
103 | - (float *)va_arg(args, double *)) < 0) | |
104 | - return FALSE; | |
105 | - break; | |
106 | - case 's': { | |
107 | - gchar *str = wp_spa_json_parse_string_internal (data, len); | |
108 | - if (!str) | |
109 | - return FALSE; | |
110 | - *va_arg(args, gchar **) = str; | |
111 | - break; | |
112 | - } | |
113 | - case 'J': { | |
114 | - WpSpaJson *j = wp_spa_json_new (data, len); | |
115 | - if (!j) | |
116 | - return FALSE; | |
117 | - *va_arg(args, WpSpaJson **) = j; | |
118 | - break; | |
119 | - } | |
120 | - default: | |
121 | - return FALSE; | |
122 | - } | |
123 | - return TRUE; | |
124 | -} | |
125 | +/* Args is not a pointer in some architectures, so this needs to be a macro to | |
126 | + * avoid args being copied */ | |
127 | +#define wp_spa_json_parse_value(data,len,fmt,args) \ | |
128 | +do { \ | |
129 | + switch (*fmt) { \ | |
130 | + case 'n': \ | |
131 | + if (!spa_json_is_null (data, len)) \ | |
132 | + return FALSE; \ | |
133 | + break; \ | |
134 | + case 'b': \ | |
135 | + if (!wp_spa_json_parse_boolean_internal (data, len, \ | |
136 | + va_arg(args, gboolean *))) \ | |
137 | + return FALSE; \ | |
138 | + break; \ | |
139 | + case 'i': \ | |
140 | + if (spa_json_parse_int (data, len, va_arg(args, gint *)) < 0) \ | |
141 | + return FALSE; \ | |
142 | + break; \ | |
143 | + case 'f': \ | |
144 | + if (spa_json_parse_float (data, len, va_arg(args, float *)) < 0) \ | |
145 | + return FALSE; \ | |
146 | + break; \ | |
147 | + case 's': { \ | |
148 | + gchar *str = wp_spa_json_parse_string_internal (data, len); \ | |
149 | + if (!str) \ | |
150 | + return FALSE; \ | |
151 | + *va_arg(args, gchar **) = str; \ | |
152 | + break; \ | |
153 | + } \ | |
154 | + case 'J': { \ | |
155 | + WpSpaJson *j = wp_spa_json_new (data, len); \ | |
156 | + if (!j) \ | |
157 | + return FALSE; \ | |
158 | + *va_arg(args, WpSpaJson **) = j; \ | |
159 | + break; \ | |
160 | + } \ | |
161 | + default: \ | |
162 | + return FALSE; \ | |
163 | + } \ | |
164 | +} while(false) | |
165 | ||
166 | /*! | |
167 | * \brief Parses the object property values of a spa json object | |
168 | @@ -827,8 +825,7 @@ wp_spa_json_object_get_valist (WpSpaJson *self, va_list args) | |
169 | value = g_value_get_boxed (&item); | |
170 | ||
171 | if (g_strcmp0 (key_str, lookup_key) == 0) { | |
172 | - if (!wp_spa_json_parse_value (value->data, value->size, lookup_fmt, args)) | |
173 | - return FALSE; | |
174 | + wp_spa_json_parse_value (value->data, value->size, lookup_fmt, args); | |
175 | lookup_key = va_arg(args, const gchar *); | |
176 | if (!lookup_key) | |
177 | return TRUE; | |
178 | @@ -1366,9 +1363,12 @@ gboolean | |
179 | wp_spa_json_parser_get_value (WpSpaJsonParser *self, const gchar *fmt, | |
180 | va_list args) | |
181 | { | |
182 | - return wp_spa_json_parser_advance (self) && | |
183 | - wp_spa_json_parse_value (self->curr.cur, | |
184 | - self->curr.end - self->curr.cur, fmt, args); | |
185 | + if (wp_spa_json_parser_advance (self)) { | |
186 | + wp_spa_json_parse_value (self->curr.cur, self->curr.end - self->curr.cur, | |
187 | + fmt, args); | |
188 | + return TRUE; | |
189 | + } | |
190 | + return FALSE; | |
191 | } | |
192 | ||
193 | /*! | |
194 | @@ -1419,9 +1419,13 @@ wp_spa_json_parser_get_valist (WpSpaJsonParser *self, va_list args) | |
195 | if (!format) | |
196 | return TRUE; | |
197 | ||
198 | - /* parse value */ | |
199 | - if (!wp_spa_json_parser_get_value (self, format, args)) | |
200 | + /* advance */ | |
201 | + if (!wp_spa_json_parser_advance (self)) | |
202 | return FALSE; | |
203 | + | |
204 | + /* parse value */ | |
205 | + wp_spa_json_parse_value (self->curr.cur, self->curr.end - self->curr.cur, | |
206 | + format, args); | |
207 | } while (TRUE); | |
208 | ||
209 | return FALSE; | |
210 | -- | |
211 | GitLab | |
212 |