Coverage Report

Created: 2026-08-13 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/librabbitmq/librabbitmq/amqp_table.c
Line
Count
Source
1
// Copyright 2007 - 2021, Alan Antonuk and the rabbitmq-c contributors.
2
// SPDX-License-Identifier: mit
3
4
#ifdef HAVE_CONFIG_H
5
#include "config.h"
6
#endif
7
8
#include "amqp_private.h"
9
#include "amqp_table.h"
10
#include <assert.h>
11
#include <stdint.h>
12
#include <stdio.h>
13
#include <stdlib.h>
14
#include <string.h>
15
16
606k
#define INITIAL_ARRAY_SIZE 16
17
76.2k
#define INITIAL_TABLE_SIZE 16
18
61.0M
#define TABLE_DEPTH_LIMIT 100
19
20
static int amqp_decode_field_value(amqp_bytes_t encoded, amqp_pool_t *pool,
21
                                   amqp_field_value_t *entry, size_t *offset,
22
                                   int depth);
23
24
static int amqp_encode_field_value(amqp_bytes_t encoded,
25
                                   amqp_field_value_t *entry, size_t *offset);
26
27
/*---------------------------------------------------------------------------*/
28
29
static int amqp_decode_array(amqp_bytes_t encoded, amqp_pool_t *pool,
30
606k
                             amqp_array_t *output, size_t *offset, int depth) {
31
606k
  uint32_t arraysize;
32
606k
  int num_entries = 0;
33
606k
  int allocated_entries = INITIAL_ARRAY_SIZE;
34
606k
  amqp_field_value_t *entries;
35
606k
  size_t limit;
36
606k
  int res;
37
38
606k
  if (!amqp_decode_32(encoded, offset, &arraysize)) {
39
104
    return AMQP_STATUS_BAD_AMQP_DATA;
40
104
  }
41
42
606k
  if (arraysize + *offset > encoded.len) {
43
322
    return AMQP_STATUS_BAD_AMQP_DATA;
44
322
  }
45
46
605k
  entries = malloc(allocated_entries * sizeof(amqp_field_value_t));
47
605k
  if (entries == NULL) {
48
0
    return AMQP_STATUS_NO_MEMORY;
49
0
  }
50
51
605k
  limit = *offset + arraysize;
52
60.6M
  while (*offset < limit) {
53
60.0M
    if (num_entries >= allocated_entries) {
54
918k
      void *newentries;
55
918k
      allocated_entries = allocated_entries * 2;
56
918k
      newentries =
57
918k
          realloc(entries, allocated_entries * sizeof(amqp_field_value_t));
58
918k
      res = AMQP_STATUS_NO_MEMORY;
59
918k
      if (newentries == NULL) {
60
0
        goto out;
61
0
      }
62
63
918k
      entries = newentries;
64
918k
    }
65
66
60.0M
    res = amqp_decode_field_value(encoded, pool, &entries[num_entries], offset,
67
60.0M
                                  depth);
68
60.0M
    if (res < 0) {
69
23.5k
      goto out;
70
23.5k
    }
71
72
60.0M
    num_entries++;
73
60.0M
  }
74
75
582k
  output->num_entries = num_entries;
76
582k
  output->entries =
77
582k
      amqp_pool_alloc(pool, num_entries * sizeof(amqp_field_value_t));
78
  /* NULL is legitimate if we requested a zero-length block. */
79
582k
  if (output->entries == NULL) {
80
49.7k
    if (num_entries == 0) {
81
49.7k
      res = AMQP_STATUS_OK;
82
49.7k
    } else {
83
0
      res = AMQP_STATUS_NO_MEMORY;
84
0
    }
85
49.7k
    goto out;
86
49.7k
  }
87
88
532k
  memcpy(output->entries, entries, num_entries * sizeof(amqp_field_value_t));
89
532k
  res = AMQP_STATUS_OK;
90
91
605k
out:
92
605k
  free(entries);
93
605k
  return res;
94
532k
}
95
96
static int amqp_decode_table_internal(amqp_bytes_t encoded, amqp_pool_t *pool,
97
                                      amqp_table_t *output, size_t *offset,
98
76.2k
                                      int depth) {
99
76.2k
  uint32_t tablesize;
100
76.2k
  int num_entries = 0;
101
76.2k
  amqp_table_entry_t *entries;
102
76.2k
  int allocated_entries = INITIAL_TABLE_SIZE;
103
76.2k
  size_t limit;
104
76.2k
  int res;
105
106
76.2k
  if (!amqp_decode_32(encoded, offset, &tablesize)) {
107
189
    return AMQP_STATUS_BAD_AMQP_DATA;
108
189
  }
109
110
76.1k
  if (tablesize + *offset > encoded.len) {
111
972
    return AMQP_STATUS_BAD_AMQP_DATA;
112
972
  }
113
114
75.1k
  entries = malloc(allocated_entries * sizeof(amqp_table_entry_t));
115
75.1k
  if (entries == NULL) {
116
0
    return AMQP_STATUS_NO_MEMORY;
117
0
  }
118
119
75.1k
  limit = *offset + tablesize;
120
1.03M
  while (*offset < limit) {
121
962k
    uint8_t keylen;
122
123
962k
    res = AMQP_STATUS_BAD_AMQP_DATA;
124
962k
    if (!amqp_decode_8(encoded, offset, &keylen)) {
125
0
      goto out;
126
0
    }
127
128
962k
    if (num_entries >= allocated_entries) {
129
7.82k
      void *newentries;
130
7.82k
      allocated_entries = allocated_entries * 2;
131
7.82k
      newentries =
132
7.82k
          realloc(entries, allocated_entries * sizeof(amqp_table_entry_t));
133
7.82k
      res = AMQP_STATUS_NO_MEMORY;
134
7.82k
      if (newentries == NULL) {
135
0
        goto out;
136
0
      }
137
138
7.82k
      entries = newentries;
139
7.82k
    }
140
141
962k
    res = AMQP_STATUS_BAD_AMQP_DATA;
142
962k
    if (!amqp_decode_bytes(encoded, offset, &entries[num_entries].key,
143
962k
                           keylen)) {
144
123
      goto out;
145
123
    }
146
147
962k
    res = amqp_decode_field_value(encoded, pool, &entries[num_entries].value,
148
962k
                                  offset, depth);
149
962k
    if (res < 0) {
150
7.46k
      goto out;
151
7.46k
    }
152
153
955k
    num_entries++;
154
955k
  }
155
156
67.5k
  output->num_entries = num_entries;
157
67.5k
  output->entries =
158
67.5k
      amqp_pool_alloc(pool, num_entries * sizeof(amqp_table_entry_t));
159
  /* NULL is legitimate if we requested a zero-length block. */
160
67.5k
  if (output->entries == NULL) {
161
18.2k
    if (num_entries == 0) {
162
18.2k
      res = AMQP_STATUS_OK;
163
18.2k
    } else {
164
0
      res = AMQP_STATUS_NO_MEMORY;
165
0
    }
166
18.2k
    goto out;
167
18.2k
  }
168
169
49.2k
  memcpy(output->entries, entries, num_entries * sizeof(amqp_table_entry_t));
170
49.2k
  res = AMQP_STATUS_OK;
171
172
75.1k
out:
173
75.1k
  free(entries);
174
75.1k
  return res;
175
49.2k
}
176
177
int amqp_decode_table(amqp_bytes_t encoded, amqp_pool_t *pool,
178
9.65k
                      amqp_table_t *output, size_t *offset) {
179
9.65k
  return amqp_decode_table_internal(encoded, pool, output, offset, 0);
180
9.65k
}
181
182
static int amqp_decode_field_value(amqp_bytes_t encoded, amqp_pool_t *pool,
183
                                   amqp_field_value_t *entry, size_t *offset,
184
61.0M
                                   int depth) {
185
61.0M
  int res = AMQP_STATUS_BAD_AMQP_DATA;
186
187
61.0M
  if (depth > TABLE_DEPTH_LIMIT) {
188
25
    return AMQP_STATUS_BAD_AMQP_DATA;
189
25
  }
190
191
61.0M
  if (!amqp_decode_8(encoded, offset, &entry->kind)) {
192
124
    goto out;
193
124
  }
194
195
61.0M
#define TRIVIAL_FIELD_DECODER(bits)                                          \
196
61.0M
  if (!amqp_decode_##bits(encoded, offset, &entry->value.u##bits)) goto out; \
197
7.84M
  break
198
61.0M
#define SIMPLE_FIELD_DECODER(bits, dest, how)                 \
199
61.0M
  {                                                           \
200
9.04M
    uint##bits##_t val;                                       \
201
9.04M
    if (!amqp_decode_##bits(encoded, offset, &val)) goto out; \
202
11.7M
    entry->value.dest = how;                                  \
203
9.04M
  }                                                           \
204
9.04M
  break
205
206
61.0M
  switch (entry->kind) {
207
5.87M
    case AMQP_FIELD_KIND_BOOLEAN:
208
5.87M
      SIMPLE_FIELD_DECODER(8, boolean, val ? 1 : 0);
209
210
1.16M
    case AMQP_FIELD_KIND_I8:
211
1.16M
      SIMPLE_FIELD_DECODER(8, i8, (int8_t)val);
212
5.03M
    case AMQP_FIELD_KIND_U8:
213
5.03M
      TRIVIAL_FIELD_DECODER(8);
214
215
5.03M
    case AMQP_FIELD_KIND_I16:
216
1.38M
      SIMPLE_FIELD_DECODER(16, i16, (int16_t)val);
217
1.19M
    case AMQP_FIELD_KIND_U16:
218
1.19M
      TRIVIAL_FIELD_DECODER(16);
219
220
1.19M
    case AMQP_FIELD_KIND_I32:
221
254k
      SIMPLE_FIELD_DECODER(32, i32, (int32_t)val);
222
286k
    case AMQP_FIELD_KIND_U32:
223
286k
      TRIVIAL_FIELD_DECODER(32);
224
225
368k
    case AMQP_FIELD_KIND_I64:
226
368k
      SIMPLE_FIELD_DECODER(64, i64, (int64_t)val);
227
89.0k
    case AMQP_FIELD_KIND_U64:
228
89.0k
      TRIVIAL_FIELD_DECODER(64);
229
230
634k
    case AMQP_FIELD_KIND_F32:
231
634k
      TRIVIAL_FIELD_DECODER(32);
232
      /* and by punning, f32 magically gets the right value...! */
233
234
634k
    case AMQP_FIELD_KIND_F64:
235
296k
      TRIVIAL_FIELD_DECODER(64);
236
      /* and by punning, f64 magically gets the right value...! */
237
238
352k
    case AMQP_FIELD_KIND_DECIMAL:
239
352k
      if (!amqp_decode_8(encoded, offset, &entry->value.decimal.decimals) ||
240
351k
          !amqp_decode_32(encoded, offset, &entry->value.decimal.value)) {
241
128
        goto out;
242
128
      }
243
351k
      break;
244
245
351k
    case AMQP_FIELD_KIND_UTF8:
246
    /* AMQP_FIELD_KIND_UTF8 and AMQP_FIELD_KIND_BYTES have the
247
       same implementation, but different interpretations. */
248
    /* fall through */
249
119k
    case AMQP_FIELD_KIND_BYTES: {
250
119k
      uint32_t len;
251
119k
      if (!amqp_decode_32(encoded, offset, &len) ||
252
119k
          !amqp_decode_bytes(encoded, offset, &entry->value.bytes, len)) {
253
398
        goto out;
254
398
      }
255
119k
      break;
256
119k
    }
257
258
606k
    case AMQP_FIELD_KIND_ARRAY:
259
606k
      res = amqp_decode_array(encoded, pool, &(entry->value.array), offset,
260
606k
                              depth + 1);
261
606k
      goto out;
262
263
304k
    case AMQP_FIELD_KIND_TIMESTAMP:
264
304k
      TRIVIAL_FIELD_DECODER(64);
265
266
304k
    case AMQP_FIELD_KIND_TABLE:
267
66.6k
      res = amqp_decode_table_internal(encoded, pool, &(entry->value.table),
268
66.6k
                                       offset, depth + 1);
269
66.6k
      goto out;
270
271
42.9M
    case AMQP_FIELD_KIND_VOID:
272
42.9M
      break;
273
274
543
    default:
275
543
      goto out;
276
61.0M
  }
277
278
60.3M
  res = AMQP_STATUS_OK;
279
280
61.0M
out:
281
61.0M
  return res;
282
60.3M
}
283
284
/*---------------------------------------------------------------------------*/
285
286
static int amqp_encode_array(amqp_bytes_t encoded, amqp_array_t *input,
287
143k
                             size_t *offset) {
288
143k
  size_t start = *offset;
289
143k
  int i, res;
290
291
143k
  *offset += 4; /* size of the array gets filled in later on */
292
293
7.96M
  for (i = 0; i < input->num_entries; i++) {
294
7.82M
    res = amqp_encode_field_value(encoded, &input->entries[i], offset);
295
7.82M
    if (res < 0) {
296
0
      goto out;
297
0
    }
298
7.82M
  }
299
300
143k
  if (!amqp_encode_32(encoded, &start, (uint32_t)(*offset - start - 4))) {
301
0
    res = AMQP_STATUS_TABLE_TOO_BIG;
302
0
    goto out;
303
0
  }
304
305
143k
  res = AMQP_STATUS_OK;
306
307
143k
out:
308
143k
  return res;
309
143k
}
310
311
int amqp_encode_table(amqp_bytes_t encoded, amqp_table_t *input,
312
18.0k
                      size_t *offset) {
313
18.0k
  size_t start = *offset;
314
18.0k
  int i, res;
315
316
18.0k
  *offset += 4; /* size of the table gets filled in later on */
317
318
57.5k
  for (i = 0; i < input->num_entries; i++) {
319
39.4k
    if (!amqp_encode_8(encoded, offset, (uint8_t)input->entries[i].key.len)) {
320
0
      res = AMQP_STATUS_TABLE_TOO_BIG;
321
0
      goto out;
322
0
    }
323
324
39.4k
    if (!amqp_encode_bytes(encoded, offset, input->entries[i].key)) {
325
0
      res = AMQP_STATUS_TABLE_TOO_BIG;
326
0
      goto out;
327
0
    }
328
329
39.4k
    res = amqp_encode_field_value(encoded, &input->entries[i].value, offset);
330
39.4k
    if (res < 0) {
331
0
      goto out;
332
0
    }
333
39.4k
  }
334
335
18.0k
  if (!amqp_encode_32(encoded, &start, (uint32_t)(*offset - start - 4))) {
336
0
    res = AMQP_STATUS_TABLE_TOO_BIG;
337
0
    goto out;
338
0
  }
339
340
18.0k
  res = AMQP_STATUS_OK;
341
342
18.0k
out:
343
18.0k
  return res;
344
18.0k
}
345
346
static int amqp_encode_field_value(amqp_bytes_t encoded,
347
7.86M
                                   amqp_field_value_t *entry, size_t *offset) {
348
7.86M
  int res = AMQP_STATUS_BAD_AMQP_DATA;
349
350
7.86M
  if (!amqp_encode_8(encoded, offset, entry->kind)) {
351
0
    goto out;
352
0
  }
353
354
7.86M
#define FIELD_ENCODER(bits, val)                   \
355
7.86M
  if (!amqp_encode_##bits(encoded, offset, val)) { \
356
0
    res = AMQP_STATUS_TABLE_TOO_BIG;               \
357
0
    goto out;                                      \
358
0
  }                                                \
359
4.12M
  break
360
361
7.86M
  switch (entry->kind) {
362
2.35M
    case AMQP_FIELD_KIND_BOOLEAN:
363
2.35M
      FIELD_ENCODER(8, entry->value.boolean ? 1 : 0);
364
365
2.35M
    case AMQP_FIELD_KIND_I8:
366
886k
      FIELD_ENCODER(8, entry->value.i8);
367
886k
    case AMQP_FIELD_KIND_U8:
368
44.2k
      FIELD_ENCODER(8, entry->value.u8);
369
370
44.2k
    case AMQP_FIELD_KIND_I16:
371
20.3k
      FIELD_ENCODER(16, entry->value.i16);
372
308k
    case AMQP_FIELD_KIND_U16:
373
308k
      FIELD_ENCODER(16, entry->value.u16);
374
375
308k
    case AMQP_FIELD_KIND_I32:
376
23.0k
      FIELD_ENCODER(32, entry->value.i32);
377
131k
    case AMQP_FIELD_KIND_U32:
378
131k
      FIELD_ENCODER(32, entry->value.u32);
379
380
131k
    case AMQP_FIELD_KIND_I64:
381
52.5k
      FIELD_ENCODER(64, entry->value.i64);
382
52.5k
    case AMQP_FIELD_KIND_U64:
383
43.4k
      FIELD_ENCODER(64, entry->value.u64);
384
385
139k
    case AMQP_FIELD_KIND_F32:
386
      /* by punning, u32 magically gets the right value...! */
387
139k
      FIELD_ENCODER(32, entry->value.u32);
388
389
139k
    case AMQP_FIELD_KIND_F64:
390
      /* by punning, u64 magically gets the right value...! */
391
75.2k
      FIELD_ENCODER(64, entry->value.u64);
392
393
119k
    case AMQP_FIELD_KIND_DECIMAL:
394
119k
      if (!amqp_encode_8(encoded, offset, entry->value.decimal.decimals) ||
395
119k
          !amqp_encode_32(encoded, offset, entry->value.decimal.value)) {
396
0
        res = AMQP_STATUS_TABLE_TOO_BIG;
397
0
        goto out;
398
0
      }
399
119k
      break;
400
401
119k
    case AMQP_FIELD_KIND_UTF8:
402
    /* AMQP_FIELD_KIND_UTF8 and AMQP_FIELD_KIND_BYTES have the
403
       same implementation, but different interpretations. */
404
    /* fall through */
405
9.64k
    case AMQP_FIELD_KIND_BYTES:
406
9.64k
      if (!amqp_encode_32(encoded, offset, (uint32_t)entry->value.bytes.len) ||
407
9.64k
          !amqp_encode_bytes(encoded, offset, entry->value.bytes)) {
408
0
        res = AMQP_STATUS_TABLE_TOO_BIG;
409
0
        goto out;
410
0
      }
411
9.64k
      break;
412
413
143k
    case AMQP_FIELD_KIND_ARRAY:
414
143k
      res = amqp_encode_array(encoded, &entry->value.array, offset);
415
143k
      goto out;
416
417
45.5k
    case AMQP_FIELD_KIND_TIMESTAMP:
418
45.5k
      FIELD_ENCODER(64, entry->value.u64);
419
420
45.5k
    case AMQP_FIELD_KIND_TABLE:
421
16.4k
      res = amqp_encode_table(encoded, &entry->value.table, offset);
422
16.4k
      goto out;
423
424
3.44M
    case AMQP_FIELD_KIND_VOID:
425
3.44M
      break;
426
427
0
    default:
428
0
      res = AMQP_STATUS_INVALID_PARAMETER;
429
0
      goto out;
430
7.86M
  }
431
432
7.70M
  res = AMQP_STATUS_OK;
433
434
7.86M
out:
435
7.86M
  return res;
436
7.70M
}
437
438
/*---------------------------------------------------------------------------*/
439
440
0
int amqp_table_entry_cmp(void const *entry1, void const *entry2) {
441
0
  amqp_table_entry_t const *p1 = (amqp_table_entry_t const *)entry1;
442
0
  amqp_table_entry_t const *p2 = (amqp_table_entry_t const *)entry2;
443
444
0
  int d;
445
0
  size_t minlen;
446
447
0
  minlen = p1->key.len;
448
0
  if (p2->key.len < minlen) {
449
0
    minlen = p2->key.len;
450
0
  }
451
452
0
  d = memcmp(p1->key.bytes, p2->key.bytes, minlen);
453
0
  if (d != 0) {
454
0
    return d;
455
0
  }
456
457
0
  return (int)p1->key.len - (int)p2->key.len;
458
0
}
459
460
static int amqp_field_value_clone(const amqp_field_value_t *original,
461
                                  amqp_field_value_t *clone,
462
5.86M
                                  amqp_pool_t *pool) {
463
5.86M
  int i;
464
5.86M
  int res;
465
5.86M
  clone->kind = original->kind;
466
467
5.86M
  switch (clone->kind) {
468
2.23M
    case AMQP_FIELD_KIND_BOOLEAN:
469
2.23M
      clone->value.boolean = original->value.boolean;
470
2.23M
      break;
471
472
545k
    case AMQP_FIELD_KIND_I8:
473
545k
      clone->value.i8 = original->value.i8;
474
545k
      break;
475
476
19.9k
    case AMQP_FIELD_KIND_U8:
477
19.9k
      clone->value.u8 = original->value.u8;
478
19.9k
      break;
479
480
11.8k
    case AMQP_FIELD_KIND_I16:
481
11.8k
      clone->value.i16 = original->value.i16;
482
11.8k
      break;
483
484
170k
    case AMQP_FIELD_KIND_U16:
485
170k
      clone->value.u16 = original->value.u16;
486
170k
      break;
487
488
19.2k
    case AMQP_FIELD_KIND_I32:
489
19.2k
      clone->value.i32 = original->value.i32;
490
19.2k
      break;
491
492
77.2k
    case AMQP_FIELD_KIND_U32:
493
77.2k
      clone->value.u32 = original->value.u32;
494
77.2k
      break;
495
496
35.7k
    case AMQP_FIELD_KIND_I64:
497
35.7k
      clone->value.i64 = original->value.i64;
498
35.7k
      break;
499
500
23.0k
    case AMQP_FIELD_KIND_U64:
501
46.8k
    case AMQP_FIELD_KIND_TIMESTAMP:
502
46.8k
      clone->value.u64 = original->value.u64;
503
46.8k
      break;
504
505
72.2k
    case AMQP_FIELD_KIND_F32:
506
72.2k
      clone->value.f32 = original->value.f32;
507
72.2k
      break;
508
509
9.78k
    case AMQP_FIELD_KIND_F64:
510
9.78k
      clone->value.f64 = original->value.f64;
511
9.78k
      break;
512
513
77.7k
    case AMQP_FIELD_KIND_DECIMAL:
514
77.7k
      clone->value.decimal = original->value.decimal;
515
77.7k
      break;
516
517
2.62k
    case AMQP_FIELD_KIND_UTF8:
518
3.26k
    case AMQP_FIELD_KIND_BYTES:
519
3.26k
      if (0 == original->value.bytes.len) {
520
2.32k
        clone->value.bytes = amqp_empty_bytes;
521
2.32k
      } else {
522
934
        amqp_pool_alloc_bytes(pool, original->value.bytes.len,
523
934
                              &clone->value.bytes);
524
934
        if (NULL == clone->value.bytes.bytes) {
525
0
          return AMQP_STATUS_NO_MEMORY;
526
0
        }
527
934
        memcpy(clone->value.bytes.bytes, original->value.bytes.bytes,
528
934
               clone->value.bytes.len);
529
934
      }
530
3.26k
      break;
531
532
88.5k
    case AMQP_FIELD_KIND_ARRAY:
533
88.5k
      if (0 == original->value.array.entries) {
534
753
        clone->value.array = amqp_empty_array;
535
87.7k
      } else {
536
87.7k
        clone->value.array.num_entries = original->value.array.num_entries;
537
87.7k
        clone->value.array.entries = amqp_pool_alloc(
538
87.7k
            pool, clone->value.array.num_entries * sizeof(amqp_field_value_t));
539
87.7k
        if (NULL == clone->value.array.entries) {
540
0
          return AMQP_STATUS_NO_MEMORY;
541
0
        }
542
543
5.94M
        for (i = 0; i < clone->value.array.num_entries; ++i) {
544
5.85M
          res = amqp_field_value_clone(&original->value.array.entries[i],
545
5.85M
                                       &clone->value.array.entries[i], pool);
546
5.85M
          if (AMQP_STATUS_OK != res) {
547
514
            return res;
548
514
          }
549
5.85M
        }
550
87.7k
      }
551
88.0k
      break;
552
553
88.0k
    case AMQP_FIELD_KIND_TABLE:
554
6.50k
      return amqp_table_clone(&original->value.table, &clone->value.table,
555
6.50k
                              pool);
556
557
2.44M
    case AMQP_FIELD_KIND_VOID:
558
2.44M
      break;
559
560
0
    default:
561
0
      return AMQP_STATUS_INVALID_PARAMETER;
562
5.86M
  }
563
564
5.86M
  return AMQP_STATUS_OK;
565
5.86M
}
566
567
static int amqp_table_entry_clone(const amqp_table_entry_t *original,
568
                                  amqp_table_entry_t *clone,
569
12.3k
                                  amqp_pool_t *pool) {
570
12.3k
  if (0 == original->key.len) {
571
264
    return AMQP_STATUS_INVALID_PARAMETER;
572
264
  }
573
574
12.0k
  amqp_pool_alloc_bytes(pool, original->key.len, &clone->key);
575
12.0k
  if (NULL == clone->key.bytes) {
576
0
    return AMQP_STATUS_NO_MEMORY;
577
0
  }
578
579
12.0k
  memcpy(clone->key.bytes, original->key.bytes, clone->key.len);
580
581
12.0k
  return amqp_field_value_clone(&original->value, &clone->value, pool);
582
12.0k
}
583
584
int amqp_table_clone(const amqp_table_t *original, amqp_table_t *clone,
585
7.24k
                     amqp_pool_t *pool) {
586
7.24k
  int i;
587
7.24k
  int res;
588
7.24k
  clone->num_entries = original->num_entries;
589
7.24k
  if (0 == clone->num_entries) {
590
1.95k
    *clone = amqp_empty_table;
591
1.95k
    return AMQP_STATUS_OK;
592
1.95k
  }
593
594
5.29k
  clone->entries =
595
5.29k
      amqp_pool_alloc(pool, clone->num_entries * sizeof(amqp_table_entry_t));
596
597
5.29k
  if (NULL == clone->entries) {
598
0
    return AMQP_STATUS_NO_MEMORY;
599
0
  }
600
601
17.0k
  for (i = 0; i < clone->num_entries; ++i) {
602
12.3k
    res =
603
12.3k
        amqp_table_entry_clone(&original->entries[i], &clone->entries[i], pool);
604
12.3k
    if (AMQP_STATUS_OK != res) {
605
539
      goto error_out1;
606
539
    }
607
12.3k
  }
608
609
4.75k
  return AMQP_STATUS_OK;
610
611
539
error_out1:
612
539
  return res;
613
5.29k
}
614
615
amqp_table_entry_t amqp_table_construct_utf8_entry(const char *key,
616
0
                                                   const char *value) {
617
0
  amqp_table_entry_t ret;
618
0
  ret.key = amqp_cstring_bytes(key);
619
0
  ret.value.kind = AMQP_FIELD_KIND_UTF8;
620
0
  ret.value.value.bytes = amqp_cstring_bytes(value);
621
0
  return ret;
622
0
}
623
624
amqp_table_entry_t amqp_table_construct_table_entry(const char *key,
625
0
                                                    const amqp_table_t *value) {
626
0
  amqp_table_entry_t ret;
627
0
  ret.key = amqp_cstring_bytes(key);
628
0
  ret.value.kind = AMQP_FIELD_KIND_TABLE;
629
0
  ret.value.value.table = *value;
630
0
  return ret;
631
0
}
632
633
amqp_table_entry_t amqp_table_construct_bool_entry(const char *key,
634
0
                                                   const int value) {
635
0
  amqp_table_entry_t ret;
636
0
  ret.key = amqp_cstring_bytes(key);
637
0
  ret.value.kind = AMQP_FIELD_KIND_BOOLEAN;
638
0
  ret.value.value.boolean = value;
639
0
  return ret;
640
0
}
641
642
amqp_table_entry_t *amqp_table_get_entry_by_key(const amqp_table_t *table,
643
0
                                                const amqp_bytes_t key) {
644
0
  int i;
645
0
  assert(table != NULL);
646
0
  for (i = 0; i < table->num_entries; ++i) {
647
0
    if (amqp_bytes_equal(table->entries[i].key, key)) {
648
0
      return &table->entries[i];
649
0
    }
650
0
  }
651
0
  return NULL;
652
0
}