Skip to content

Commit e70a294

Browse files
niedbalskiedsiper
authored andcommitted
ra: fix subkey_to_object to support direct array access
Record Accessor API couldn't handle direct array access patterns like $array[0]. This fix changes the condition that checks if a lookup succeeded by replacing !found with matched == 0, which properly tracks array element access. Added test cases to verify array access works: - Direct array access ($array[0]) - Nested array access ($matrix[1][2]) - Mixed array and map access ($records[1]['name']) - Access with out-of-bounds indices - Nonexistent key access - Type mismatch handling - Nested path failures Fixes #9958 Signed-off-by: Jorge Niedbalski <[email protected]>
1 parent 92393d4 commit e70a294

File tree

1 file changed

+21
-16
lines changed

1 file changed

+21
-16
lines changed

src/flb_ra_key.c

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,11 @@ static int msgpack_object_strcmp(msgpack_object o, char *str, int len)
121121

122122
/* Lookup perfect match of sub-keys and map content */
123123
static int subkey_to_object(msgpack_object *map, struct mk_list *subkeys,
124-
msgpack_object **out_key, msgpack_object **out_val)
124+
msgpack_object **out_key, msgpack_object **out_val)
125125
{
126126
int i = 0;
127127
int levels;
128128
int matched = 0;
129-
msgpack_object *found = NULL;
130129
msgpack_object *key = NULL;
131130
msgpack_object *val = NULL;
132131
msgpack_object cur;
@@ -136,6 +135,11 @@ static int subkey_to_object(msgpack_object *map, struct mk_list *subkeys,
136135
/* Expected number of map levels in the map */
137136
levels = mk_list_size(subkeys);
138137

138+
/* Early return if no subkeys */
139+
if (levels == 0) {
140+
return -1;
141+
}
142+
139143
cur = *map;
140144

141145
mk_list_foreach(head, subkeys) {
@@ -150,40 +154,41 @@ static int subkey_to_object(msgpack_object *map, struct mk_list *subkeys,
150154
}
151155

152156
/* Index limit and ensure no overflow */
153-
if (entry->array_id == INT_MAX ||
154-
cur.via.array.size < entry->array_id + 1) {
157+
if (entry->array_id == INT_MAX || entry->array_id >= cur.via.array.size) {
155158
return -1;
156159
}
157160

158161
val = &cur.via.array.ptr[entry->array_id];
159162
cur = *val;
160163
key = NULL; /* fill NULL since the type is array. */
161-
goto next;
164+
matched++;
165+
166+
if (levels == matched) {
167+
break;
168+
}
169+
170+
continue;
162171
}
163172

173+
/* Handle map objects */
164174
if (cur.type != MSGPACK_OBJECT_MAP) {
165175
break;
166176
}
167177

168178
i = ra_key_val_id(entry->str, cur);
169179
if (i == -1) {
170-
found = NULL;
171-
continue;
180+
continue; /* Try next entry */
172181
}
173182

174183
key = &cur.via.map.ptr[i].key;
175184
val = &cur.via.map.ptr[i].val;
176185

177186
/* A bit obvious, but it's better to validate data type */
178187
if (key->type != MSGPACK_OBJECT_STR) {
179-
found = NULL;
180-
continue;
188+
continue; /* Try next entry */
181189
}
182190

183-
found = key;
184-
cur = cur.via.map.ptr[i].val;
185-
186-
next:
191+
cur = *val;
187192
matched++;
188193

189194
if (levels == matched) {
@@ -192,12 +197,12 @@ static int subkey_to_object(msgpack_object *map, struct mk_list *subkeys,
192197
}
193198

194199
/* No matches */
195-
if (!found || (matched > 0 && levels != matched)) {
200+
if (matched == 0 || (matched > 0 && levels != matched)) {
196201
return -1;
197202
}
198203

199-
*out_key = (msgpack_object *) key;
200-
*out_val = (msgpack_object *) val;
204+
*out_key = key;
205+
*out_val = val;
201206

202207
return 0;
203208
}

0 commit comments

Comments
 (0)