blob: 75c7b850f4ad5adb2aef30b951a606ac8149baf3 [file] [log] [blame]
Andrew Geissler9aee5002022-03-30 16:27:02 +00001From e429db7e8c266045aee25e153fb2308bd61fe233 Mon Sep 17 00:00:00 2001
2From: Julian Bouzas <julian.bouzas@collabora.com>
3Date: Wed, 9 Feb 2022 07:59:59 -0500
4Subject: [PATCH] spa-json: fix va_list APIs for different architectures
5
6The va_list type might not always be a pointer in some architectures, so we
7cannot guarantee it will be modified after using it for a second time in another
8function. This fixes the issue by using macros so args does not get copied, and
9always gets modified when using it more than once.
10
11Upstream-Status: Backport [https://gitlab.freedesktop.org/pipewire/wireplumber/-/commit/e429db7e8c266045aee25e153fb2308bd61fe233]
12
13Signed-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
19diff --git a/lib/wp/spa-json.c b/lib/wp/spa-json.c
20index 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--
2162.32.0
217