pg_query 2.0.3 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/README.md +12 -0
  4. data/Rakefile +5 -19
  5. data/ext/pg_query/extconf.rb +3 -1
  6. data/ext/pg_query/include/c.h +12 -0
  7. data/ext/pg_query/include/executor/executor.h +6 -0
  8. data/ext/pg_query/include/nodes/execnodes.h +9 -6
  9. data/ext/pg_query/include/nodes/pathnodes.h +1 -1
  10. data/ext/pg_query/include/optimizer/paths.h +8 -0
  11. data/ext/pg_query/include/pg_config.h +6 -6
  12. data/ext/pg_query/include/pg_config_manual.h +7 -0
  13. data/ext/pg_query/include/pg_query.h +2 -2
  14. data/ext/pg_query/include/pg_query_outfuncs_defs.c +1 -0
  15. data/ext/pg_query/include/pg_query_readfuncs_defs.c +1 -0
  16. data/ext/pg_query/include/protobuf-c.h +7 -3
  17. data/ext/pg_query/include/protobuf-c/protobuf-c.h +7 -3
  18. data/ext/pg_query/include/protobuf/pg_query.pb-c.h +472 -467
  19. data/ext/pg_query/include/utils/array.h +1 -0
  20. data/ext/pg_query/include/utils/lsyscache.h +1 -0
  21. data/ext/pg_query/include/utils/probes.h +57 -57
  22. data/ext/pg_query/pg_query.pb-c.c +502 -487
  23. data/ext/pg_query/pg_query_deparse.c +6 -0
  24. data/ext/pg_query/pg_query_fingerprint.c +104 -32
  25. data/ext/pg_query/pg_query_normalize.c +112 -60
  26. data/ext/pg_query/protobuf-c.c +34 -27
  27. data/ext/pg_query/src_backend_utils_mmgr_mcxt.c +36 -0
  28. data/ext/pg_query/src_common_hashfn.c +420 -0
  29. data/lib/pg_query.rb +0 -1
  30. data/lib/pg_query/filter_columns.rb +1 -1
  31. data/lib/pg_query/fingerprint.rb +1 -3
  32. data/lib/pg_query/parse.rb +60 -5
  33. data/lib/pg_query/pg_query_pb.rb +1385 -1383
  34. data/lib/pg_query/version.rb +1 -1
  35. metadata +7 -7
  36. data/lib/pg_query/json_field_names.rb +0 -1402
@@ -2247,6 +2247,12 @@ static void deparseRangeVar(StringInfo str, RangeVar *range_var, DeparseNodeCont
2247
2247
  if (!range_var->inh && context != DEPARSE_NODE_CONTEXT_CREATE_TYPE && context != DEPARSE_NODE_CONTEXT_ALTER_TYPE)
2248
2248
  appendStringInfoString(str, "ONLY ");
2249
2249
 
2250
+ if (range_var->catalogname != NULL)
2251
+ {
2252
+ appendStringInfoString(str, quote_identifier(range_var->catalogname));
2253
+ appendStringInfoChar(str, '.');
2254
+ }
2255
+
2250
2256
  if (range_var->schemaname != NULL)
2251
2257
  {
2252
2258
  appendStringInfoString(str, quote_identifier(range_var->schemaname));
@@ -17,6 +17,8 @@
17
17
  #include "nodes/parsenodes.h"
18
18
  #include "nodes/value.h"
19
19
 
20
+ #include "common/hashfn.h"
21
+
20
22
  #include <unistd.h>
21
23
  #include <fcntl.h>
22
24
 
@@ -26,15 +28,41 @@ typedef struct FingerprintContext
26
28
  {
27
29
  XXH3_state_t *xxh_state;
28
30
 
31
+ struct listsort_cache_hash *listsort_cache;
32
+
29
33
  bool write_tokens;
30
34
  dlist_head tokens;
31
35
  } FingerprintContext;
32
36
 
33
- typedef struct FingerprintListContext
37
+ typedef struct FingerprintListsortItem
34
38
  {
35
39
  XXH64_hash_t hash;
36
40
  size_t list_pos;
37
- } FingerprintListContext;
41
+ } FingerprintListsortItem;
42
+
43
+ typedef struct FingerprintListsortItemCacheEntry
44
+ {
45
+ /* List node this cache entry is for */
46
+ uintptr_t node;
47
+
48
+ /* Hashes of all list items -- this is expensive to calculate */
49
+ FingerprintListsortItem **listsort_items;
50
+ size_t listsort_items_size;
51
+
52
+ /* hash entry status */
53
+ char status;
54
+ } FingerprintListsortItemCacheEntry;
55
+
56
+ #define SH_PREFIX listsort_cache
57
+ #define SH_ELEMENT_TYPE FingerprintListsortItemCacheEntry
58
+ #define SH_KEY_TYPE uintptr_t
59
+ #define SH_KEY node
60
+ #define SH_HASH_KEY(tb, key) hash_bytes((const unsigned char *) &key, sizeof(uintptr_t))
61
+ #define SH_EQUAL(tb, a, b) a == b
62
+ #define SH_SCOPE static inline
63
+ #define SH_DEFINE
64
+ #define SH_DECLARE
65
+ #include "lib/simplehash.h"
38
66
 
39
67
  typedef struct FingerprintToken
40
68
  {
@@ -43,7 +71,7 @@ typedef struct FingerprintToken
43
71
  } FingerprintToken;
44
72
 
45
73
  static void _fingerprintNode(FingerprintContext *ctx, const void *obj, const void *parent, char *parent_field_name, unsigned int depth);
46
- static void _fingerprintInitContext(FingerprintContext *ctx, bool write_tokens);
74
+ static void _fingerprintInitContext(FingerprintContext *ctx, FingerprintContext *parent, bool write_tokens);
47
75
  static void _fingerprintFreeContext(FingerprintContext *ctx);
48
76
 
49
77
  #define PG_QUERY_FINGERPRINT_VERSION 3
@@ -96,10 +124,10 @@ _fingerprintBitString(FingerprintContext *ctx, const Value *node)
96
124
  }
97
125
  }
98
126
 
99
- static int compareFingerprintListContext(const void *a, const void *b)
127
+ static int compareFingerprintListsortItem(const void *a, const void *b)
100
128
  {
101
- FingerprintListContext *ca = *(FingerprintListContext**) a;
102
- FingerprintListContext *cb = *(FingerprintListContext**) b;
129
+ FingerprintListsortItem *ca = *(FingerprintListsortItem**) a;
130
+ FingerprintListsortItem *cb = *(FingerprintListsortItem**) b;
103
131
  if (ca->hash > cb->hash)
104
132
  return 1;
105
133
  else if (ca->hash < cb->hash)
@@ -111,38 +139,69 @@ static void
111
139
  _fingerprintList(FingerprintContext *ctx, const List *node, const void *parent, char *field_name, unsigned int depth)
112
140
  {
113
141
  if (field_name != NULL && (strcmp(field_name, "fromClause") == 0 || strcmp(field_name, "targetList") == 0 ||
114
- strcmp(field_name, "cols") == 0 || strcmp(field_name, "rexpr") == 0 || strcmp(field_name, "valuesLists") == 0 ||
115
- strcmp(field_name, "args") == 0)) {
142
+ strcmp(field_name, "cols") == 0 || strcmp(field_name, "rexpr") == 0 || strcmp(field_name, "valuesLists") == 0 ||
143
+ strcmp(field_name, "args") == 0))
144
+ {
145
+ /*
146
+ * Check for cached values for the hashes of subnodes
147
+ *
148
+ * Note this cache is important so we avoid exponential runtime behavior,
149
+ * which would be the case if we fingerprinted each node twice, which
150
+ * then would also again have to fingerprint each of its subnodes twice,
151
+ * etc., leading to deep nodes to be fingerprinted many many times over.
152
+ *
153
+ * We have seen real-world problems with this logic here without
154
+ * a cache in place.
155
+ */
156
+ FingerprintListsortItem** listsort_items = NULL;
157
+ size_t listsort_items_size = 0;
158
+ FingerprintListsortItemCacheEntry *entry = listsort_cache_lookup(ctx->listsort_cache, (uintptr_t) node);
159
+ if (entry != NULL)
160
+ {
161
+ listsort_items = entry->listsort_items;
162
+ listsort_items_size = entry->listsort_items_size;
163
+ }
164
+ else
165
+ {
166
+ listsort_items = palloc0(node->length * sizeof(FingerprintListsortItem*));
167
+ listsort_items_size = 0;
168
+ ListCell *lc;
169
+ bool found;
116
170
 
117
- FingerprintListContext** listCtxArr = palloc0(node->length * sizeof(FingerprintListContext*));
118
- size_t listCtxCount = 0;
119
- const ListCell *lc;
171
+ foreach(lc, node)
172
+ {
173
+ FingerprintContext fctx;
174
+ FingerprintListsortItem* lctx = palloc0(sizeof(FingerprintListsortItem));
120
175
 
121
- foreach(lc, node)
122
- {
123
- FingerprintContext subCtx;
124
- FingerprintListContext* listCtx = palloc0(sizeof(FingerprintListContext));
176
+ _fingerprintInitContext(&fctx, ctx, false);
177
+ _fingerprintNode(&fctx, lfirst(lc), parent, field_name, depth + 1);
178
+ lctx->hash = XXH3_64bits_digest(fctx.xxh_state);
179
+ lctx->list_pos = listsort_items_size;
180
+ _fingerprintFreeContext(&fctx);
125
181
 
126
- _fingerprintInitContext(&subCtx, false);
127
- _fingerprintNode(&subCtx, lfirst(lc), parent, field_name, depth + 1);
128
- listCtx->hash = XXH3_64bits_digest(subCtx.xxh_state);
129
- listCtx->list_pos = listCtxCount;
130
- _fingerprintFreeContext(&subCtx);
182
+ listsort_items[listsort_items_size] = lctx;
183
+ listsort_items_size += 1;
184
+ }
131
185
 
132
- listCtxArr[listCtxCount] = listCtx;
133
- listCtxCount += 1;
134
- }
186
+ pg_qsort(listsort_items, listsort_items_size, sizeof(FingerprintListsortItem*), compareFingerprintListsortItem);
135
187
 
136
- pg_qsort(listCtxArr, listCtxCount, sizeof(FingerprintListContext*), compareFingerprintListContext);
188
+ FingerprintListsortItemCacheEntry *entry = listsort_cache_insert(ctx->listsort_cache, (uintptr_t) node, &found);
189
+ Assert(!found);
137
190
 
138
- for (size_t i = 0; i < listCtxCount; i++)
191
+ entry->listsort_items = listsort_items;
192
+ entry->listsort_items_size = listsort_items_size;
193
+ }
194
+
195
+ for (size_t i = 0; i < listsort_items_size; i++)
139
196
  {
140
- if (i > 0 && listCtxArr[i - 1]->hash == listCtxArr[i]->hash)
197
+ if (i > 0 && listsort_items[i - 1]->hash == listsort_items[i]->hash)
141
198
  continue; // Ignore duplicates
142
199
 
143
- _fingerprintNode(ctx, lfirst(list_nth_cell(node, listCtxArr[i]->list_pos)), parent, field_name, depth + 1);
200
+ _fingerprintNode(ctx, lfirst(list_nth_cell(node, listsort_items[i]->list_pos)), parent, field_name, depth + 1);
144
201
  }
145
- } else {
202
+ }
203
+ else
204
+ {
146
205
  const ListCell *lc;
147
206
 
148
207
  foreach(lc, node)
@@ -155,15 +214,28 @@ _fingerprintList(FingerprintContext *ctx, const List *node, const void *parent,
155
214
  }
156
215
 
157
216
  static void
158
- _fingerprintInitContext(FingerprintContext *ctx, bool write_tokens) {
217
+ _fingerprintInitContext(FingerprintContext *ctx, FingerprintContext *parent, bool write_tokens)
218
+ {
159
219
  ctx->xxh_state = XXH3_createState();
160
220
  if (ctx->xxh_state == NULL) abort();
161
221
  if (XXH3_64bits_reset_withSeed(ctx->xxh_state, PG_QUERY_FINGERPRINT_VERSION) == XXH_ERROR) abort();
162
222
 
163
- if (write_tokens) {
223
+ if (parent != NULL)
224
+ {
225
+ ctx->listsort_cache = parent->listsort_cache;
226
+ }
227
+ else
228
+ {
229
+ ctx->listsort_cache = listsort_cache_create(CurrentMemoryContext, 128, NULL);
230
+ }
231
+
232
+ if (write_tokens)
233
+ {
164
234
  ctx->write_tokens = true;
165
235
  dlist_init(&ctx->tokens);
166
- } else {
236
+ }
237
+ else
238
+ {
167
239
  ctx->write_tokens = false;
168
240
  }
169
241
  }
@@ -237,7 +309,7 @@ PgQueryFingerprintResult pg_query_fingerprint_with_opts(const char* input, bool
237
309
  FingerprintContext ctx;
238
310
  XXH64_canonical_t chash;
239
311
 
240
- _fingerprintInitContext(&ctx, printTokens);
312
+ _fingerprintInitContext(&ctx, NULL, printTokens);
241
313
 
242
314
  if (parsetree_and_error.tree != NULL) {
243
315
  _fingerprintNode(&ctx, parsetree_and_error.tree, NULL, NULL, 0);
@@ -303,71 +303,123 @@ static bool const_record_walker(Node *node, pgssConstLocations *jstate)
303
303
 
304
304
  if (node == NULL) return false;
305
305
 
306
- if (IsA(node, A_Const))
306
+ switch (nodeTag(node))
307
307
  {
308
- RecordConstLocation(jstate, castNode(A_Const, node)->location);
309
- }
310
- else if (IsA(node, ParamRef))
311
- {
312
- /* Track the highest ParamRef number */
313
- if (((ParamRef *) node)->number > jstate->highest_extern_param_id)
314
- jstate->highest_extern_param_id = castNode(ParamRef, node)->number;
315
- }
316
- else if (IsA(node, DefElem))
317
- {
318
- DefElem * defElem = (DefElem *) node;
319
- if (defElem->arg != NULL && IsA(defElem->arg, String)) {
320
- for (int i = defElem->location; i < jstate->query_len; i++) {
321
- if (jstate->query[i] == '\'') {
322
- RecordConstLocation(jstate, i);
323
- break;
324
- }
308
+ case T_A_Const:
309
+ RecordConstLocation(jstate, castNode(A_Const, node)->location);
310
+ break;
311
+ case T_ParamRef:
312
+ {
313
+ /* Track the highest ParamRef number */
314
+ if (((ParamRef *) node)->number > jstate->highest_extern_param_id)
315
+ jstate->highest_extern_param_id = castNode(ParamRef, node)->number;
325
316
  }
326
- }
327
- return const_record_walker((Node *) ((DefElem *) node)->arg, jstate);
328
- }
329
- else if (IsA(node, RawStmt))
330
- {
331
- return const_record_walker((Node *) ((RawStmt *) node)->stmt, jstate);
332
- }
333
- else if (IsA(node, VariableSetStmt))
334
- {
335
- return const_record_walker((Node *) ((VariableSetStmt *) node)->args, jstate);
336
- }
337
- else if (IsA(node, CopyStmt))
338
- {
339
- return const_record_walker((Node *) ((CopyStmt *) node)->query, jstate);
340
- }
341
- else if (IsA(node, ExplainStmt))
342
- {
343
- return const_record_walker((Node *) ((ExplainStmt *) node)->query, jstate);
344
- }
345
- else if (IsA(node, CreateRoleStmt))
346
- {
347
- return const_record_walker((Node *) ((CreateRoleStmt *) node)->options, jstate);
348
- }
349
- else if (IsA(node, AlterRoleStmt))
350
- {
351
- return const_record_walker((Node *) ((AlterRoleStmt *) node)->options, jstate);
352
- }
353
- else if (IsA(node, DeclareCursorStmt))
354
- {
355
- return const_record_walker((Node *) ((DeclareCursorStmt *) node)->query, jstate);
356
- }
317
+ break;
318
+ case T_DefElem:
319
+ {
320
+ DefElem * defElem = (DefElem *) node;
321
+ if (defElem->arg != NULL && IsA(defElem->arg, String)) {
322
+ for (int i = defElem->location; i < jstate->query_len; i++) {
323
+ if (jstate->query[i] == '\'') {
324
+ RecordConstLocation(jstate, i);
325
+ break;
326
+ }
327
+ }
328
+ }
329
+ return const_record_walker((Node *) ((DefElem *) node)->arg, jstate);
330
+ }
331
+ break;
332
+ case T_RawStmt:
333
+ return const_record_walker((Node *) ((RawStmt *) node)->stmt, jstate);
334
+ case T_VariableSetStmt:
335
+ return const_record_walker((Node *) ((VariableSetStmt *) node)->args, jstate);
336
+ case T_CopyStmt:
337
+ return const_record_walker((Node *) ((CopyStmt *) node)->query, jstate);
338
+ case T_ExplainStmt:
339
+ return const_record_walker((Node *) ((ExplainStmt *) node)->query, jstate);
340
+ case T_CreateRoleStmt:
341
+ return const_record_walker((Node *) ((CreateRoleStmt *) node)->options, jstate);
342
+ case T_AlterRoleStmt:
343
+ return const_record_walker((Node *) ((AlterRoleStmt *) node)->options, jstate);
344
+ case T_DeclareCursorStmt:
345
+ return const_record_walker((Node *) ((DeclareCursorStmt *) node)->query, jstate);
346
+ case T_SelectStmt:
347
+ {
348
+ SelectStmt *stmt = (SelectStmt *) node;
349
+ ListCell *lc;
350
+
351
+ if (const_record_walker((Node *) stmt->distinctClause, jstate))
352
+ return true;
353
+ if (const_record_walker((Node *) stmt->intoClause, jstate))
354
+ return true;
355
+ if (const_record_walker((Node *) stmt->targetList, jstate))
356
+ return true;
357
+ if (const_record_walker((Node *) stmt->fromClause, jstate))
358
+ return true;
359
+ if (const_record_walker((Node *) stmt->whereClause, jstate))
360
+ return true;
361
+
362
+ // Instead of walking all of groupClause (like raw_expression_tree_walker does),
363
+ // only walk certain items.
364
+ foreach(lc, stmt->groupClause)
365
+ {
366
+ // Do not walk A_Const values that are simple integers, this avoids
367
+ // turning "GROUP BY 1" into "GROUP BY $n", which obscures an important
368
+ // semantic meaning. This matches how pg_stat_statements handles the
369
+ // GROUP BY clause (i.e. it doesn't touch these constants)
370
+ if (IsA(lfirst(lc), A_Const) && IsA(&castNode(A_Const, lfirst(lc))->val, Integer))
371
+ continue;
372
+
373
+ if (const_record_walker((Node *) lfirst(lc), jstate))
374
+ return true;
375
+ }
376
+ foreach(lc, stmt->sortClause)
377
+ {
378
+ // Similarly, don't turn "ORDER BY 1" into "ORDER BY $n"
379
+ if (IsA(lfirst(lc), SortBy) && IsA(castNode(SortBy, lfirst(lc))->node, A_Const) &&
380
+ IsA(&castNode(A_Const, castNode(SortBy, lfirst(lc))->node)->val, Integer))
381
+ continue;
357
382
 
358
- PG_TRY();
359
- {
360
- result = raw_expression_tree_walker(node, const_record_walker, (void*) jstate);
361
- }
362
- PG_CATCH();
363
- {
364
- MemoryContextSwitchTo(normalize_context);
365
- result = false;
366
- FlushErrorState();
383
+ if (const_record_walker((Node *) lfirst(lc), jstate))
384
+ return true;
385
+ }
386
+ if (const_record_walker((Node *) stmt->havingClause, jstate))
387
+ return true;
388
+ if (const_record_walker((Node *) stmt->windowClause, jstate))
389
+ return true;
390
+ if (const_record_walker((Node *) stmt->valuesLists, jstate))
391
+ return true;
392
+ if (const_record_walker((Node *) stmt->limitOffset, jstate))
393
+ return true;
394
+ if (const_record_walker((Node *) stmt->limitCount, jstate))
395
+ return true;
396
+ if (const_record_walker((Node *) stmt->lockingClause, jstate))
397
+ return true;
398
+ if (const_record_walker((Node *) stmt->withClause, jstate))
399
+ return true;
400
+ if (const_record_walker((Node *) stmt->larg, jstate))
401
+ return true;
402
+ if (const_record_walker((Node *) stmt->rarg, jstate))
403
+ return true;
404
+
405
+ return false;
406
+ }
407
+ default:
408
+ {
409
+ PG_TRY();
410
+ {
411
+ return raw_expression_tree_walker(node, const_record_walker, (void*) jstate);
412
+ }
413
+ PG_CATCH();
414
+ {
415
+ MemoryContextSwitchTo(normalize_context);
416
+ FlushErrorState();
417
+ }
418
+ PG_END_TRY();
419
+ }
367
420
  }
368
- PG_END_TRY();
369
421
 
370
- return result;
422
+ return false;
371
423
  }
372
424
 
373
425
  PgQueryNormalizeResult pg_query_normalize(const char* input)
@@ -84,7 +84,9 @@
84
84
  # define PROTOBUF_C_UNPACK_ERROR(...)
85
85
  #endif
86
86
 
87
+ #if !defined(_WIN32) || !defined(PROTOBUF_C_USE_SHARED_LIB)
87
88
  const char protobuf_c_empty_string[] = "";
89
+ #endif
88
90
 
89
91
  /**
90
92
  * Internal `ProtobufCMessage` manipulation macro.
@@ -148,12 +150,14 @@ protobuf_c_version_number(void)
148
150
  static void *
149
151
  system_alloc(void *allocator_data, size_t size)
150
152
  {
153
+ (void)allocator_data;
151
154
  return malloc(size);
152
155
  }
153
156
 
154
157
  static void
155
158
  system_free(void *allocator_data, void *data)
156
159
  {
160
+ (void)allocator_data;
157
161
  free(data);
158
162
  }
159
163
 
@@ -1618,22 +1622,19 @@ required_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1618
1622
  break;
1619
1623
  }
1620
1624
  case PROTOBUF_C_TYPE_MESSAGE: {
1621
- uint8_t simple_buffer_scratch[256];
1622
- size_t sublen;
1623
1625
  const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
1624
- ProtobufCBufferSimple simple_buffer =
1625
- PROTOBUF_C_BUFFER_SIMPLE_INIT(simple_buffer_scratch);
1626
-
1626
+
1627
1627
  scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1628
- if (msg == NULL)
1629
- sublen = 0;
1630
- else
1631
- sublen = protobuf_c_message_pack_to_buffer(msg, &simple_buffer.base);
1632
- rv += uint32_pack(sublen, scratch + rv);
1633
- buffer->append(buffer, rv, scratch);
1634
- buffer->append(buffer, sublen, simple_buffer.data);
1635
- rv += sublen;
1636
- PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple_buffer);
1628
+ if (msg == NULL) {
1629
+ rv += uint32_pack(0, scratch + rv);
1630
+ buffer->append(buffer, rv, scratch);
1631
+ } else {
1632
+ size_t sublen = protobuf_c_message_get_packed_size(msg);
1633
+ rv += uint32_pack(sublen, scratch + rv);
1634
+ buffer->append(buffer, rv, scratch);
1635
+ protobuf_c_message_pack_to_buffer(msg, buffer);
1636
+ rv += sublen;
1637
+ }
1637
1638
  break;
1638
1639
  }
1639
1640
  default:
@@ -2063,7 +2064,7 @@ static size_t
2063
2064
  parse_tag_and_wiretype(size_t len,
2064
2065
  const uint8_t *data,
2065
2066
  uint32_t *tag_out,
2066
- ProtobufCWireType *wiretype_out)
2067
+ uint8_t *wiretype_out)
2067
2068
  {
2068
2069
  unsigned max_rv = len > 5 ? 5 : len;
2069
2070
  uint32_t tag = (data[0] & 0x7f) >> 3;
@@ -2095,9 +2096,9 @@ parse_tag_and_wiretype(size_t len,
2095
2096
 
2096
2097
  /* sizeof(ScannedMember) must be <= (1UL<<BOUND_SIZEOF_SCANNED_MEMBER_LOG2) */
2097
2098
  #define BOUND_SIZEOF_SCANNED_MEMBER_LOG2 5
2098
- typedef struct _ScannedMember ScannedMember;
2099
+ typedef struct ScannedMember ScannedMember;
2099
2100
  /** Field as it's being read. */
2100
- struct _ScannedMember {
2101
+ struct ScannedMember {
2101
2102
  uint32_t tag; /**< Field tag. */
2102
2103
  uint8_t wire_type; /**< Field type. */
2103
2104
  uint8_t length_prefix_len; /**< Prefix length. */
@@ -2132,11 +2133,13 @@ scan_length_prefixed_data(size_t len, const uint8_t *data,
2132
2133
  // Protobuf messages should always be less than 2 GiB in size.
2133
2134
  // We also want to return early here so that hdr_len + val does
2134
2135
  // not overflow on 32-bit systems.
2135
- PROTOBUF_C_UNPACK_ERROR("length prefix of %lu is too large", val);
2136
+ PROTOBUF_C_UNPACK_ERROR("length prefix of %lu is too large",
2137
+ (unsigned long int)val);
2136
2138
  return 0;
2137
2139
  }
2138
2140
  if (hdr_len + val > len) {
2139
- PROTOBUF_C_UNPACK_ERROR("data too short after length-prefix of %lu", val);
2141
+ PROTOBUF_C_UNPACK_ERROR("data too short after length-prefix of %lu",
2142
+ (unsigned long int)val);
2140
2143
  return 0;
2141
2144
  }
2142
2145
  return hdr_len + val;
@@ -2498,7 +2501,7 @@ parse_required_member(ScannedMember *scanned_member,
2498
2501
  {
2499
2502
  unsigned len = scanned_member->len;
2500
2503
  const uint8_t *data = scanned_member->data;
2501
- ProtobufCWireType wire_type = scanned_member->wire_type;
2504
+ uint8_t wire_type = scanned_member->wire_type;
2502
2505
 
2503
2506
  switch (scanned_member->field->type) {
2504
2507
  case PROTOBUF_C_TYPE_ENUM:
@@ -2579,7 +2582,7 @@ parse_required_member(ScannedMember *scanned_member,
2579
2582
  {
2580
2583
  do_free(allocator, bd->data);
2581
2584
  }
2582
- if (len - pref_len > 0) {
2585
+ if (len > pref_len) {
2583
2586
  bd->data = do_alloc(allocator, len - pref_len);
2584
2587
  if (bd->data == NULL)
2585
2588
  return FALSE;
@@ -2747,7 +2750,9 @@ parse_packed_repeated_member(ScannedMember *scanned_member,
2747
2750
  const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len;
2748
2751
  size_t rem = scanned_member->len - scanned_member->length_prefix_len;
2749
2752
  size_t count = 0;
2753
+ #if defined(WORDS_BIGENDIAN)
2750
2754
  unsigned i;
2755
+ #endif
2751
2756
 
2752
2757
  switch (field->type) {
2753
2758
  case PROTOBUF_C_TYPE_SFIXED32:
@@ -2840,13 +2845,15 @@ parse_packed_repeated_member(ScannedMember *scanned_member,
2840
2845
  }
2841
2846
  break;
2842
2847
  case PROTOBUF_C_TYPE_BOOL:
2843
- count = rem;
2844
- for (i = 0; i < count; i++) {
2845
- if (at[i] > 1) {
2848
+ while (rem > 0) {
2849
+ unsigned s = scan_varint(rem, at);
2850
+ if (s == 0) {
2846
2851
  PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value");
2847
2852
  return FALSE;
2848
2853
  }
2849
- ((protobuf_c_boolean *) array)[i] = at[i];
2854
+ ((protobuf_c_boolean *) array)[count++] = parse_boolean(s, at);
2855
+ at += s;
2856
+ rem -= s;
2850
2857
  }
2851
2858
  break;
2852
2859
  default:
@@ -3080,7 +3087,7 @@ protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc,
3080
3087
 
3081
3088
  while (rem > 0) {
3082
3089
  uint32_t tag;
3083
- ProtobufCWireType wire_type;
3090
+ uint8_t wire_type;
3084
3091
  size_t used = parse_tag_and_wiretype(rem, at, &tag, &wire_type);
3085
3092
  const ProtobufCFieldDescriptor *field;
3086
3093
  ScannedMember tmp;
@@ -3657,4 +3664,4 @@ protobuf_c_service_descriptor_get_method_by_name(const ProtobufCServiceDescripto
3657
3664
  if (strcmp(desc->methods[desc->method_indices_by_name[start]].name, name) == 0)
3658
3665
  return desc->methods + desc->method_indices_by_name[start];
3659
3666
  return NULL;
3660
- }
3667
+ }