Coverage Report

Created: 2025-07-12 06:50

/src/nghttp2/lib/nghttp2_hd.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * nghttp2 - HTTP/2 C Library
3
 *
4
 * Copyright (c) 2013 Tatsuhiro Tsujikawa
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining
7
 * a copy of this software and associated documentation files (the
8
 * "Software"), to deal in the Software without restriction, including
9
 * without limitation the rights to use, copy, modify, merge, publish,
10
 * distribute, sublicense, and/or sell copies of the Software, and to
11
 * permit persons to whom the Software is furnished to do so, subject to
12
 * the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be
15
 * included in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
 */
25
#include "nghttp2_hd.h"
26
27
#include <string.h>
28
#include <assert.h>
29
#include <stdio.h>
30
31
#include "nghttp2_helper.h"
32
#include "nghttp2_int.h"
33
#include "nghttp2_debug.h"
34
35
/* Make scalar initialization form of nghttp2_hd_entry */
36
#define MAKE_STATIC_ENT(N, V, T, H)                                            \
37
  {                                                                            \
38
    {NULL, NULL, (uint8_t *)(N), sizeof((N)) - 1, -1},                         \
39
    {NULL, NULL, (uint8_t *)(V), sizeof((V)) - 1, -1},                         \
40
    {(uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0},     \
41
    T,                                                                         \
42
    H,                                                                         \
43
  }
44
45
/* Generated by mkstatictbl.py */
46
/* 3rd parameter is nghttp2_token value for header field name.  We use
47
   first enum value if same header names are repeated (e.g.,
48
   :status). */
49
static const nghttp2_hd_static_entry static_table[] = {
50
  MAKE_STATIC_ENT(":authority", "", 0, 3153725150u),
51
  MAKE_STATIC_ENT(":method", "GET", 1, 695666056u),
52
  MAKE_STATIC_ENT(":method", "POST", 1, 695666056u),
53
  MAKE_STATIC_ENT(":path", "/", 3, 3292848686u),
54
  MAKE_STATIC_ENT(":path", "/index.html", 3, 3292848686u),
55
  MAKE_STATIC_ENT(":scheme", "http", 5, 2510477674u),
56
  MAKE_STATIC_ENT(":scheme", "https", 5, 2510477674u),
57
  MAKE_STATIC_ENT(":status", "200", 7, 4000288983u),
58
  MAKE_STATIC_ENT(":status", "204", 7, 4000288983u),
59
  MAKE_STATIC_ENT(":status", "206", 7, 4000288983u),
60
  MAKE_STATIC_ENT(":status", "304", 7, 4000288983u),
61
  MAKE_STATIC_ENT(":status", "400", 7, 4000288983u),
62
  MAKE_STATIC_ENT(":status", "404", 7, 4000288983u),
63
  MAKE_STATIC_ENT(":status", "500", 7, 4000288983u),
64
  MAKE_STATIC_ENT("accept-charset", "", 14, 3664010344u),
65
  MAKE_STATIC_ENT("accept-encoding", "gzip, deflate", 15, 3379649177u),
66
  MAKE_STATIC_ENT("accept-language", "", 16, 1979086614u),
67
  MAKE_STATIC_ENT("accept-ranges", "", 17, 1713753958u),
68
  MAKE_STATIC_ENT("accept", "", 18, 136609321u),
69
  MAKE_STATIC_ENT("access-control-allow-origin", "", 19, 2710797292u),
70
  MAKE_STATIC_ENT("age", "", 20, 742476188u),
71
  MAKE_STATIC_ENT("allow", "", 21, 2930878514u),
72
  MAKE_STATIC_ENT("authorization", "", 22, 2436257726u),
73
  MAKE_STATIC_ENT("cache-control", "", 23, 1355326669u),
74
  MAKE_STATIC_ENT("content-disposition", "", 24, 3889184348u),
75
  MAKE_STATIC_ENT("content-encoding", "", 25, 65203592u),
76
  MAKE_STATIC_ENT("content-language", "", 26, 24973587u),
77
  MAKE_STATIC_ENT("content-length", "", 27, 1308181789u),
78
  MAKE_STATIC_ENT("content-location", "", 28, 2302364718u),
79
  MAKE_STATIC_ENT("content-range", "", 29, 3555523146u),
80
  MAKE_STATIC_ENT("content-type", "", 30, 4244048277u),
81
  MAKE_STATIC_ENT("cookie", "", 31, 2007449791u),
82
  MAKE_STATIC_ENT("date", "", 32, 3564297305u),
83
  MAKE_STATIC_ENT("etag", "", 33, 113792960u),
84
  MAKE_STATIC_ENT("expect", "", 34, 2530896728u),
85
  MAKE_STATIC_ENT("expires", "", 35, 1049544579u),
86
  MAKE_STATIC_ENT("from", "", 36, 2513272949u),
87
  MAKE_STATIC_ENT("host", "", 37, 2952701295u),
88
  MAKE_STATIC_ENT("if-match", "", 38, 3597694698u),
89
  MAKE_STATIC_ENT("if-modified-since", "", 39, 2213050793u),
90
  MAKE_STATIC_ENT("if-none-match", "", 40, 2536202615u),
91
  MAKE_STATIC_ENT("if-range", "", 41, 2340978238u),
92
  MAKE_STATIC_ENT("if-unmodified-since", "", 42, 3794814858u),
93
  MAKE_STATIC_ENT("last-modified", "", 43, 3226950251u),
94
  MAKE_STATIC_ENT("link", "", 44, 232457833u),
95
  MAKE_STATIC_ENT("location", "", 45, 200649126u),
96
  MAKE_STATIC_ENT("max-forwards", "", 46, 1826162134u),
97
  MAKE_STATIC_ENT("proxy-authenticate", "", 47, 2709445359u),
98
  MAKE_STATIC_ENT("proxy-authorization", "", 48, 2686392507u),
99
  MAKE_STATIC_ENT("range", "", 49, 4208725202u),
100
  MAKE_STATIC_ENT("referer", "", 50, 3969579366u),
101
  MAKE_STATIC_ENT("refresh", "", 51, 3572655668u),
102
  MAKE_STATIC_ENT("retry-after", "", 52, 3336180598u),
103
  MAKE_STATIC_ENT("server", "", 53, 1085029842u),
104
  MAKE_STATIC_ENT("set-cookie", "", 54, 1848371000u),
105
  MAKE_STATIC_ENT("strict-transport-security", "", 55, 4138147361u),
106
  MAKE_STATIC_ENT("transfer-encoding", "", 56, 3719590988u),
107
  MAKE_STATIC_ENT("user-agent", "", 57, 606444526u),
108
  MAKE_STATIC_ENT("vary", "", 58, 1085005381u),
109
  MAKE_STATIC_ENT("via", "", 59, 1762798611u),
110
  MAKE_STATIC_ENT("www-authenticate", "", 60, 779865858u),
111
};
112
113
16.0k
static int memeq(const void *s1, const void *s2, size_t n) {
114
16.0k
  return memcmp(s1, s2, n) == 0;
115
16.0k
}
116
117
/*
118
 * This function was generated by genlibtokenlookup.py.  Inspired by
119
 * h2o header lookup.  https://github.com/h2o/h2o
120
 */
121
19.2k
static int32_t lookup_token(const uint8_t *name, size_t namelen) {
122
19.2k
  switch (namelen) {
123
896
  case 2:
124
896
    switch (name[1]) {
125
680
    case 'e':
126
680
      if (memeq("t", name, 1)) {
127
470
        return NGHTTP2_TOKEN_TE;
128
470
      }
129
210
      break;
130
896
    }
131
426
    break;
132
1.06k
  case 3:
133
1.06k
    switch (name[2]) {
134
430
    case 'a':
135
430
      if (memeq("vi", name, 2)) {
136
194
        return NGHTTP2_TOKEN_VIA;
137
194
      }
138
236
      break;
139
422
    case 'e':
140
422
      if (memeq("ag", name, 2)) {
141
194
        return NGHTTP2_TOKEN_AGE;
142
194
      }
143
228
      break;
144
1.06k
    }
145
679
    break;
146
2.38k
  case 4:
147
2.38k
    switch (name[3]) {
148
303
    case 'e':
149
303
      if (memeq("dat", name, 3)) {
150
66
        return NGHTTP2_TOKEN_DATE;
151
66
      }
152
237
      break;
153
419
    case 'g':
154
419
      if (memeq("eta", name, 3)) {
155
194
        return NGHTTP2_TOKEN_ETAG;
156
194
      }
157
225
      break;
158
422
    case 'k':
159
422
      if (memeq("lin", name, 3)) {
160
194
        return NGHTTP2_TOKEN_LINK;
161
194
      }
162
228
      break;
163
432
    case 'm':
164
432
      if (memeq("fro", name, 3)) {
165
194
        return NGHTTP2_TOKEN_FROM;
166
194
      }
167
238
      break;
168
301
    case 't':
169
301
      if (memeq("hos", name, 3)) {
170
194
        return NGHTTP2_TOKEN_HOST;
171
194
      }
172
107
      break;
173
433
    case 'y':
174
433
      if (memeq("var", name, 3)) {
175
194
        return NGHTTP2_TOKEN_VARY;
176
194
      }
177
239
      break;
178
2.38k
    }
179
1.34k
    break;
180
1.34k
  case 5:
181
722
    switch (name[4]) {
182
261
    case 'e':
183
261
      if (memeq("rang", name, 4)) {
184
66
        return NGHTTP2_TOKEN_RANGE;
185
66
      }
186
195
      break;
187
195
    case 'h':
188
133
      if (memeq(":pat", name, 4)) {
189
66
        return NGHTTP2_TOKEN__PATH;
190
66
      }
191
67
      break;
192
134
    case 'w':
193
134
      if (memeq("allo", name, 4)) {
194
66
        return NGHTTP2_TOKEN_ALLOW;
195
66
      }
196
68
      break;
197
722
    }
198
524
    break;
199
914
  case 6:
200
914
    switch (name[5]) {
201
260
    case 'e':
202
260
      if (memeq("cooki", name, 5)) {
203
66
        return NGHTTP2_TOKEN_COOKIE;
204
66
      }
205
194
      break;
206
194
    case 'r':
207
132
      if (memeq("serve", name, 5)) {
208
66
        return NGHTTP2_TOKEN_SERVER;
209
66
      }
210
66
      break;
211
327
    case 't':
212
327
      if (memeq("accep", name, 5)) {
213
66
        return NGHTTP2_TOKEN_ACCEPT;
214
66
      }
215
261
      if (memeq("expec", name, 5)) {
216
66
        return NGHTTP2_TOKEN_EXPECT;
217
66
      }
218
195
      break;
219
914
    }
220
650
    break;
221
872
  case 7:
222
872
    switch (name[6]) {
223
133
    case 'd':
224
133
      if (memeq(":metho", name, 6)) {
225
66
        return NGHTTP2_TOKEN__METHOD;
226
66
      }
227
67
      break;
228
205
    case 'e':
229
205
      if (memeq(":schem", name, 6)) {
230
66
        return NGHTTP2_TOKEN__SCHEME;
231
66
      }
232
139
      if (memeq("upgrad", name, 6)) {
233
72
        return NGHTTP2_TOKEN_UPGRADE;
234
72
      }
235
67
      break;
236
133
    case 'h':
237
133
      if (memeq("refres", name, 6)) {
238
66
        return NGHTTP2_TOKEN_REFRESH;
239
66
      }
240
67
      break;
241
133
    case 'r':
242
133
      if (memeq("refere", name, 6)) {
243
66
        return NGHTTP2_TOKEN_REFERER;
244
66
      }
245
67
      break;
246
200
    case 's':
247
200
      if (memeq(":statu", name, 6)) {
248
66
        return NGHTTP2_TOKEN__STATUS;
249
66
      }
250
134
      if (memeq("expire", name, 6)) {
251
67
        return NGHTTP2_TOKEN_EXPIRES;
252
67
      }
253
67
      break;
254
872
    }
255
403
    break;
256
4.77k
  case 8:
257
4.77k
    switch (name[7]) {
258
133
    case 'e':
259
133
      if (memeq("if-rang", name, 7)) {
260
66
        return NGHTTP2_TOKEN_IF_RANGE;
261
66
      }
262
67
      break;
263
133
    case 'h':
264
133
      if (memeq("if-matc", name, 7)) {
265
66
        return NGHTTP2_TOKEN_IF_MATCH;
266
66
      }
267
67
      break;
268
133
    case 'n':
269
133
      if (memeq("locatio", name, 7)) {
270
66
        return NGHTTP2_TOKEN_LOCATION;
271
66
      }
272
67
      break;
273
4.30k
    case 'y':
274
4.30k
      if (memeq("priorit", name, 7)) {
275
4.23k
        return NGHTTP2_TOKEN_PRIORITY;
276
4.23k
      }
277
69
      break;
278
4.77k
    }
279
344
    break;
280
344
  case 9:
281
230
    switch (name[8]) {
282
149
    case 'l':
283
149
      if (memeq(":protoco", name, 8)) {
284
72
        return NGHTTP2_TOKEN__PROTOCOL;
285
72
      }
286
77
      break;
287
230
    }
288
158
    break;
289
720
  case 10:
290
720
    switch (name[9]) {
291
213
    case 'e':
292
213
      if (memeq("keep-aliv", name, 9)) {
293
72
        return NGHTTP2_TOKEN_KEEP_ALIVE;
294
72
      }
295
141
      if (memeq("set-cooki", name, 9)) {
296
66
        return NGHTTP2_TOKEN_SET_COOKIE;
297
66
      }
298
75
      break;
299
147
    case 'n':
300
147
      if (memeq("connectio", name, 9)) {
301
74
        return NGHTTP2_TOKEN_CONNECTION;
302
74
      }
303
73
      break;
304
148
    case 't':
305
148
      if (memeq("user-agen", name, 9)) {
306
66
        return NGHTTP2_TOKEN_USER_AGENT;
307
66
      }
308
82
      break;
309
146
    case 'y':
310
146
      if (memeq(":authorit", name, 9)) {
311
66
        return NGHTTP2_TOKEN__AUTHORITY;
312
66
      }
313
80
      break;
314
720
    }
315
376
    break;
316
376
  case 11:
317
223
    switch (name[10]) {
318
146
    case 'r':
319
146
      if (memeq("retry-afte", name, 10)) {
320
66
        return NGHTTP2_TOKEN_RETRY_AFTER;
321
66
      }
322
80
      break;
323
223
    }
324
157
    break;
325
359
  case 12:
326
359
    switch (name[11]) {
327
147
    case 'e':
328
147
      if (memeq("content-typ", name, 11)) {
329
66
        return NGHTTP2_TOKEN_CONTENT_TYPE;
330
66
      }
331
81
      break;
332
142
    case 's':
333
142
      if (memeq("max-forward", name, 11)) {
334
66
        return NGHTTP2_TOKEN_MAX_FORWARDS;
335
66
      }
336
76
      break;
337
359
    }
338
227
    break;
339
928
  case 13:
340
928
    switch (name[12]) {
341
145
    case 'd':
342
145
      if (memeq("last-modifie", name, 12)) {
343
66
        return NGHTTP2_TOKEN_LAST_MODIFIED;
344
66
      }
345
79
      break;
346
141
    case 'e':
347
141
      if (memeq("content-rang", name, 12)) {
348
66
        return NGHTTP2_TOKEN_CONTENT_RANGE;
349
66
      }
350
75
      break;
351
144
    case 'h':
352
144
      if (memeq("if-none-matc", name, 12)) {
353
66
        return NGHTTP2_TOKEN_IF_NONE_MATCH;
354
66
      }
355
78
      break;
356
144
    case 'l':
357
144
      if (memeq("cache-contro", name, 12)) {
358
66
        return NGHTTP2_TOKEN_CACHE_CONTROL;
359
66
      }
360
78
      break;
361
147
    case 'n':
362
147
      if (memeq("authorizatio", name, 12)) {
363
66
        return NGHTTP2_TOKEN_AUTHORIZATION;
364
66
      }
365
81
      break;
366
140
    case 's':
367
140
      if (memeq("accept-range", name, 12)) {
368
66
        return NGHTTP2_TOKEN_ACCEPT_RANGES;
369
66
      }
370
74
      break;
371
928
    }
372
532
    break;
373
532
  case 14:
374
352
    switch (name[13]) {
375
145
    case 'h':
376
145
      if (memeq("content-lengt", name, 13)) {
377
66
        return NGHTTP2_TOKEN_CONTENT_LENGTH;
378
66
      }
379
79
      break;
380
140
    case 't':
381
140
      if (memeq("accept-charse", name, 13)) {
382
66
        return NGHTTP2_TOKEN_ACCEPT_CHARSET;
383
66
      }
384
74
      break;
385
352
    }
386
220
    break;
387
351
  case 15:
388
351
    switch (name[14]) {
389
143
    case 'e':
390
143
      if (memeq("accept-languag", name, 14)) {
391
66
        return NGHTTP2_TOKEN_ACCEPT_LANGUAGE;
392
66
      }
393
77
      break;
394
142
    case 'g':
395
142
      if (memeq("accept-encodin", name, 14)) {
396
67
        return NGHTTP2_TOKEN_ACCEPT_ENCODING;
397
67
      }
398
75
      break;
399
351
    }
400
218
    break;
401
685
  case 16:
402
685
    switch (name[15]) {
403
218
    case 'e':
404
218
      if (memeq("content-languag", name, 15)) {
405
66
        return NGHTTP2_TOKEN_CONTENT_LANGUAGE;
406
66
      }
407
152
      if (memeq("www-authenticat", name, 15)) {
408
66
        return NGHTTP2_TOKEN_WWW_AUTHENTICATE;
409
66
      }
410
86
      break;
411
147
    case 'g':
412
147
      if (memeq("content-encodin", name, 15)) {
413
66
        return NGHTTP2_TOKEN_CONTENT_ENCODING;
414
66
      }
415
81
      break;
416
226
    case 'n':
417
226
      if (memeq("content-locatio", name, 15)) {
418
66
        return NGHTTP2_TOKEN_CONTENT_LOCATION;
419
66
      }
420
160
      if (memeq("proxy-connectio", name, 15)) {
421
72
        return NGHTTP2_TOKEN_PROXY_CONNECTION;
422
72
      }
423
88
      break;
424
685
    }
425
349
    break;
426
349
  case 17:
427
349
    switch (name[16]) {
428
140
    case 'e':
429
140
      if (memeq("if-modified-sinc", name, 16)) {
430
66
        return NGHTTP2_TOKEN_IF_MODIFIED_SINCE;
431
66
      }
432
74
      break;
433
143
    case 'g':
434
143
      if (memeq("transfer-encodin", name, 16)) {
435
66
        return NGHTTP2_TOKEN_TRANSFER_ENCODING;
436
66
      }
437
77
      break;
438
349
    }
439
217
    break;
440
217
  case 18:
441
206
    switch (name[17]) {
442
140
    case 'e':
443
140
      if (memeq("proxy-authenticat", name, 17)) {
444
66
        return NGHTTP2_TOKEN_PROXY_AUTHENTICATE;
445
66
      }
446
74
      break;
447
206
    }
448
140
    break;
449
430
  case 19:
450
430
    switch (name[18]) {
451
146
    case 'e':
452
146
      if (memeq("if-unmodified-sinc", name, 18)) {
453
66
        return NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE;
454
66
      }
455
80
      break;
456
218
    case 'n':
457
218
      if (memeq("content-dispositio", name, 18)) {
458
66
        return NGHTTP2_TOKEN_CONTENT_DISPOSITION;
459
66
      }
460
152
      if (memeq("proxy-authorizatio", name, 18)) {
461
66
        return NGHTTP2_TOKEN_PROXY_AUTHORIZATION;
462
66
      }
463
86
      break;
464
430
    }
465
232
    break;
466
232
  case 25:
467
227
    switch (name[24]) {
468
147
    case 'y':
469
147
      if (memeq("strict-transport-securit", name, 24)) {
470
66
        return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY;
471
66
      }
472
81
      break;
473
227
    }
474
161
    break;
475
180
  case 27:
476
180
    switch (name[26]) {
477
110
    case 'n':
478
110
      if (memeq("access-control-allow-origi", name, 26)) {
479
66
        return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
480
66
      }
481
44
      break;
482
180
    }
483
114
    break;
484
19.2k
  }
485
9.82k
  return -1;
486
19.2k
}
487
488
14.0k
void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv) {
489
14.0k
  ent->nv = *nv;
490
14.0k
  ent->cnv.name = nv->name->base;
491
14.0k
  ent->cnv.namelen = nv->name->len;
492
14.0k
  ent->cnv.value = nv->value->base;
493
14.0k
  ent->cnv.valuelen = nv->value->len;
494
14.0k
  ent->cnv.flags = nv->flags;
495
14.0k
  ent->next = NULL;
496
14.0k
  ent->hash = 0;
497
498
14.0k
  nghttp2_rcbuf_incref(ent->nv.name);
499
14.0k
  nghttp2_rcbuf_incref(ent->nv.value);
500
14.0k
}
501
502
14.0k
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) {
503
14.0k
  nghttp2_rcbuf_decref(ent->nv.value);
504
14.0k
  nghttp2_rcbuf_decref(ent->nv.name);
505
14.0k
}
506
507
0
static int name_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
508
0
  return a->name->len == b->namelen &&
509
0
         memeq(a->name->base, b->name, b->namelen);
510
0
}
511
512
0
static int value_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
513
0
  return a->value->len == b->valuelen &&
514
0
         memeq(a->value->base, b->value, b->valuelen);
515
0
}
516
517
0
static uint32_t name_hash(const nghttp2_nv *nv) {
518
  /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */
519
0
  uint32_t h = 2166136261u;
520
0
  size_t i;
521
522
0
  for (i = 0; i < nv->namelen; ++i) {
523
0
    h ^= nv->name[i];
524
0
    h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
525
0
  }
526
527
0
  return h;
528
0
}
529
530
11.5k
static void hd_map_init(nghttp2_hd_map *map) {
531
11.5k
  memset(map, 0, sizeof(nghttp2_hd_map));
532
11.5k
}
533
534
0
static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
535
0
  nghttp2_hd_entry **bucket;
536
537
0
  bucket = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
538
539
0
  if (*bucket == NULL) {
540
0
    *bucket = ent;
541
0
    return;
542
0
  }
543
544
  /* lower index is linked near the root */
545
0
  ent->next = *bucket;
546
0
  *bucket = ent;
547
0
}
548
549
static nghttp2_hd_entry *hd_map_find(nghttp2_hd_map *map, int *exact_match,
550
                                     const nghttp2_nv *nv, int32_t token,
551
0
                                     uint32_t hash, int name_only) {
552
0
  nghttp2_hd_entry *p;
553
0
  nghttp2_hd_entry *res = NULL;
554
555
0
  *exact_match = 0;
556
557
0
  for (p = map->table[hash & (HD_MAP_SIZE - 1)]; p; p = p->next) {
558
0
    if (token != p->nv.token ||
559
0
        (token == -1 && (hash != p->hash || !name_eq(&p->nv, nv)))) {
560
0
      continue;
561
0
    }
562
0
    if (!res) {
563
0
      res = p;
564
0
      if (name_only) {
565
0
        break;
566
0
      }
567
0
    }
568
0
    if (value_eq(&p->nv, nv)) {
569
0
      res = p;
570
0
      *exact_match = 1;
571
0
      break;
572
0
    }
573
0
  }
574
575
0
  return res;
576
0
}
577
578
0
static void hd_map_remove(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
579
0
  nghttp2_hd_entry **dst;
580
581
0
  dst = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
582
583
0
  for (; *dst; dst = &(*dst)->next) {
584
0
    if (*dst != ent) {
585
0
      continue;
586
0
    }
587
588
0
    *dst = ent->next;
589
0
    ent->next = NULL;
590
0
    return;
591
0
  }
592
0
}
593
594
static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
595
23.0k
                           nghttp2_mem *mem) {
596
23.0k
  size_t size;
597
23.0k
  const size_t max_size = SIZE_MAX / sizeof(nghttp2_hd_entry *);
598
599
23.0k
  if (bufsize > max_size) {
600
0
    return NGHTTP2_ERR_NOMEM;
601
0
  }
602
603
184k
  for (size = 1; size < bufsize; size <<= 1)
604
161k
    ;
605
606
23.0k
  if (size > max_size) {
607
0
    return NGHTTP2_ERR_NOMEM;
608
0
  }
609
610
23.0k
  ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
611
23.0k
  if (ringbuf->buffer == NULL) {
612
0
    return NGHTTP2_ERR_NOMEM;
613
0
  }
614
23.0k
  ringbuf->mask = size - 1;
615
23.0k
  ringbuf->first = 0;
616
23.0k
  ringbuf->len = 0;
617
23.0k
  return 0;
618
23.0k
}
619
620
static nghttp2_hd_entry *hd_ringbuf_get(nghttp2_hd_ringbuf *ringbuf,
621
60.7k
                                        size_t idx) {
622
60.7k
  assert(idx < ringbuf->len);
623
60.7k
  return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask];
624
60.7k
}
625
626
static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
627
14.0k
                              nghttp2_mem *mem) {
628
14.0k
  size_t i;
629
14.0k
  size_t size;
630
14.0k
  nghttp2_hd_entry **buffer;
631
632
14.0k
  if (ringbuf->mask + 1 >= bufsize) {
633
14.0k
    return 0;
634
14.0k
  }
635
0
  for (size = 1; size < bufsize; size <<= 1)
636
0
    ;
637
0
  buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
638
0
  if (buffer == NULL) {
639
0
    return NGHTTP2_ERR_NOMEM;
640
0
  }
641
0
  for (i = 0; i < ringbuf->len; ++i) {
642
0
    buffer[i] = hd_ringbuf_get(ringbuf, i);
643
0
  }
644
0
  nghttp2_mem_free(mem, ringbuf->buffer);
645
0
  ringbuf->buffer = buffer;
646
0
  ringbuf->mask = size - 1;
647
0
  ringbuf->first = 0;
648
0
  return 0;
649
0
}
650
651
23.0k
static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
652
23.0k
  size_t i;
653
23.0k
  if (ringbuf == NULL) {
654
0
    return;
655
0
  }
656
35.6k
  for (i = 0; i < ringbuf->len; ++i) {
657
12.6k
    nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
658
659
12.6k
    nghttp2_hd_entry_free(ent);
660
12.6k
    nghttp2_mem_free(mem, ent);
661
12.6k
  }
662
23.0k
  nghttp2_mem_free(mem, ringbuf->buffer);
663
23.0k
}
664
665
static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf,
666
14.0k
                                 nghttp2_hd_entry *ent, nghttp2_mem *mem) {
667
14.0k
  int rv;
668
669
14.0k
  rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem);
670
671
14.0k
  if (rv != 0) {
672
0
    return rv;
673
0
  }
674
675
14.0k
  ringbuf->buffer[--ringbuf->first & ringbuf->mask] = ent;
676
14.0k
  ++ringbuf->len;
677
678
14.0k
  return 0;
679
14.0k
}
680
681
1.40k
static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) {
682
1.40k
  assert(ringbuf->len > 0);
683
1.40k
  --ringbuf->len;
684
1.40k
}
685
686
23.0k
static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
687
23.0k
  int rv;
688
23.0k
  context->mem = mem;
689
23.0k
  context->bad = 0;
690
23.0k
  context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
691
23.0k
  rv = hd_ringbuf_init(
692
23.0k
    &context->hd_table,
693
23.0k
    context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
694
23.0k
  if (rv != 0) {
695
0
    return rv;
696
0
  }
697
698
23.0k
  context->hd_table_bufsize = 0;
699
23.0k
  context->next_seq = 0;
700
701
23.0k
  return 0;
702
23.0k
}
703
704
23.0k
static void hd_context_free(nghttp2_hd_context *context) {
705
23.0k
  hd_ringbuf_free(&context->hd_table, context->mem);
706
23.0k
}
707
708
0
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) {
709
0
  return nghttp2_hd_deflate_init2(
710
0
    deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem);
711
0
}
712
713
int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
714
                             size_t max_deflate_dynamic_table_size,
715
11.5k
                             nghttp2_mem *mem) {
716
11.5k
  int rv;
717
11.5k
  rv = hd_context_init(&deflater->ctx, mem);
718
11.5k
  if (rv != 0) {
719
0
    return rv;
720
0
  }
721
722
11.5k
  hd_map_init(&deflater->map);
723
724
11.5k
  if (max_deflate_dynamic_table_size < NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE) {
725
0
    deflater->notify_table_size_change = 1;
726
0
    deflater->ctx.hd_table_bufsize_max = max_deflate_dynamic_table_size;
727
11.5k
  } else {
728
11.5k
    deflater->notify_table_size_change = 0;
729
11.5k
  }
730
731
11.5k
  deflater->deflate_hd_table_bufsize_max = max_deflate_dynamic_table_size;
732
11.5k
  deflater->min_hd_table_bufsize_max = UINT32_MAX;
733
734
11.5k
  return 0;
735
11.5k
}
736
737
11.5k
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
738
11.5k
  int rv;
739
740
11.5k
  rv = hd_context_init(&inflater->ctx, mem);
741
11.5k
  if (rv != 0) {
742
0
    goto fail;
743
0
  }
744
745
11.5k
  inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
746
11.5k
  inflater->min_hd_table_bufsize_max = UINT32_MAX;
747
748
11.5k
  inflater->nv_name_keep = NULL;
749
11.5k
  inflater->nv_value_keep = NULL;
750
751
11.5k
  inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
752
11.5k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
753
754
11.5k
  nghttp2_buf_init(&inflater->namebuf);
755
11.5k
  nghttp2_buf_init(&inflater->valuebuf);
756
757
11.5k
  inflater->namercbuf = NULL;
758
11.5k
  inflater->valuercbuf = NULL;
759
760
11.5k
  inflater->huffman_encoded = 0;
761
11.5k
  inflater->index = 0;
762
11.5k
  inflater->left = 0;
763
11.5k
  inflater->shift = 0;
764
11.5k
  inflater->index_required = 0;
765
11.5k
  inflater->no_index = 0;
766
767
11.5k
  return 0;
768
769
0
fail:
770
0
  return rv;
771
11.5k
}
772
773
141k
static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
774
141k
  nghttp2_rcbuf_decref(inflater->nv_value_keep);
775
141k
  nghttp2_rcbuf_decref(inflater->nv_name_keep);
776
777
141k
  inflater->nv_value_keep = NULL;
778
141k
  inflater->nv_name_keep = NULL;
779
141k
}
780
781
11.5k
void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
782
11.5k
  hd_context_free(&deflater->ctx);
783
11.5k
}
784
785
11.5k
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
786
11.5k
  hd_inflate_keep_free(inflater);
787
788
11.5k
  nghttp2_rcbuf_decref(inflater->valuercbuf);
789
11.5k
  nghttp2_rcbuf_decref(inflater->namercbuf);
790
791
11.5k
  hd_context_free(&inflater->ctx);
792
11.5k
}
793
794
15.8k
static size_t entry_room(size_t namelen, size_t valuelen) {
795
15.8k
  return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
796
15.8k
}
797
798
77.4k
static void emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
799
77.4k
  DEBUGF("inflatehd: header emission: %s: %s\n", nv->name->base,
800
77.4k
         nv->value->base);
801
  /* ent->ref may be 0. This happens if the encoder emits literal
802
     block larger than header table capacity with indexing. */
803
77.4k
  *nv_out = *nv;
804
77.4k
}
805
806
0
static size_t count_encoded_length(size_t n, size_t prefix) {
807
0
  size_t k = (size_t)((1 << prefix) - 1);
808
0
  size_t len = 0;
809
810
0
  if (n < k) {
811
0
    return 1;
812
0
  }
813
814
0
  n -= k;
815
0
  ++len;
816
817
0
  for (; n >= 128; n >>= 7, ++len)
818
0
    ;
819
820
0
  return len + 1;
821
0
}
822
823
0
static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
824
0
  size_t k = (size_t)((1 << prefix) - 1);
825
0
  uint8_t *begin = buf;
826
827
0
  *buf = (uint8_t)(*buf & ~k);
828
829
0
  if (n < k) {
830
0
    *buf = (uint8_t)(*buf | n);
831
0
    return 1;
832
0
  }
833
834
0
  *buf = (uint8_t)(*buf | k);
835
0
  ++buf;
836
837
0
  n -= k;
838
839
0
  for (; n >= 128; n >>= 7) {
840
0
    *buf++ = (uint8_t)((1 << 7) | (n & 0x7f));
841
0
  }
842
843
0
  *buf++ = (uint8_t)n;
844
845
0
  return (size_t)(buf - begin);
846
0
}
847
848
/*
849
 * Decodes |prefix| prefixed integer stored from |in|.  The |last|
850
 * represents the 1 beyond the last of the valid contiguous memory
851
 * region from |in|.  The decoded integer must be less than or equal
852
 * to UINT32_MAX.
853
 *
854
 * If the |initial| is nonzero, it is used as a initial value, this
855
 * function assumes the |in| starts with intermediate data.
856
 *
857
 * An entire integer is decoded successfully, decoded, the |*fin| is
858
 * set to nonzero.
859
 *
860
 * This function stores the decoded integer in |*res| if it succeed,
861
 * including partial decoding (in this case, number of shift to make
862
 * in the next call will be stored in |*shift_ptr|) and returns number
863
 * of bytes processed, or returns -1, indicating decoding error.
864
 */
865
static nghttp2_ssize decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
866
                                   uint32_t initial, size_t shift,
867
                                   const uint8_t *in, const uint8_t *last,
868
109k
                                   size_t prefix) {
869
109k
  uint32_t k = (uint8_t)((1 << prefix) - 1);
870
109k
  uint32_t n = initial;
871
109k
  const uint8_t *start = in;
872
873
109k
  *shift_ptr = 0;
874
109k
  *fin = 0;
875
876
109k
  if (n == 0) {
877
108k
    if ((*in & k) != k) {
878
105k
      *res = (*in) & k;
879
105k
      *fin = 1;
880
105k
      return 1;
881
105k
    }
882
883
3.61k
    n = k;
884
885
3.61k
    if (++in == last) {
886
123
      *res = n;
887
123
      return (nghttp2_ssize)(in - start);
888
123
    }
889
3.61k
  }
890
891
11.5k
  for (; in != last; ++in, shift += 7) {
892
10.4k
    uint32_t add = *in & 0x7f;
893
894
10.4k
    if (shift >= 32) {
895
27
      DEBUGF("inflate: shift exponent overflow\n");
896
27
      return -1;
897
27
    }
898
899
10.4k
    if ((UINT32_MAX >> shift) < add) {
900
32
      DEBUGF("inflate: integer overflow on shift\n");
901
32
      return -1;
902
32
    }
903
904
10.3k
    add <<= shift;
905
906
10.3k
    if (UINT32_MAX - add < n) {
907
35
      DEBUGF("inflate: integer overflow on addition\n");
908
35
      return -1;
909
35
    }
910
911
10.3k
    n += add;
912
913
10.3k
    if ((*in & (1 << 7)) == 0) {
914
3.05k
      break;
915
3.05k
    }
916
10.3k
  }
917
918
4.15k
  *shift_ptr = shift;
919
920
4.15k
  if (in == last) {
921
1.09k
    *res = n;
922
1.09k
    return (nghttp2_ssize)(in - start);
923
1.09k
  }
924
925
3.05k
  *res = n;
926
3.05k
  *fin = 1;
927
3.05k
  return (nghttp2_ssize)(in + 1 - start);
928
4.15k
}
929
930
0
static int emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
931
0
  int rv;
932
0
  uint8_t *bufp;
933
0
  size_t blocklen;
934
0
  uint8_t sb[16];
935
936
0
  DEBUGF("deflatehd: emit table_size=%zu\n", table_size);
937
938
0
  blocklen = count_encoded_length(table_size, 5);
939
940
0
  if (sizeof(sb) < blocklen) {
941
0
    return NGHTTP2_ERR_HEADER_COMP;
942
0
  }
943
944
0
  bufp = sb;
945
946
0
  *bufp = 0x20u;
947
948
0
  encode_length(bufp, table_size, 5);
949
950
0
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
951
0
  if (rv != 0) {
952
0
    return rv;
953
0
  }
954
955
0
  return 0;
956
0
}
957
958
0
static int emit_indexed_block(nghttp2_bufs *bufs, size_t idx) {
959
0
  int rv;
960
0
  size_t blocklen;
961
0
  uint8_t sb[16];
962
0
  uint8_t *bufp;
963
964
0
  blocklen = count_encoded_length(idx + 1, 7);
965
966
0
  DEBUGF("deflatehd: emit indexed index=%zu, %zu bytes\n", idx, blocklen);
967
968
0
  if (sizeof(sb) < blocklen) {
969
0
    return NGHTTP2_ERR_HEADER_COMP;
970
0
  }
971
972
0
  bufp = sb;
973
0
  *bufp = 0x80u;
974
0
  encode_length(bufp, idx + 1, 7);
975
976
0
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
977
0
  if (rv != 0) {
978
0
    return rv;
979
0
  }
980
981
0
  return 0;
982
0
}
983
984
0
static int emit_string(nghttp2_bufs *bufs, const uint8_t *str, size_t len) {
985
0
  int rv;
986
0
  uint8_t sb[16];
987
0
  uint8_t *bufp;
988
0
  size_t blocklen;
989
0
  size_t enclen;
990
0
  int huffman = 0;
991
992
0
  enclen = nghttp2_hd_huff_encode_count(str, len);
993
994
0
  if (enclen < len) {
995
0
    huffman = 1;
996
0
  } else {
997
0
    enclen = len;
998
0
  }
999
1000
0
  blocklen = count_encoded_length(enclen, 7);
1001
1002
0
  DEBUGF("deflatehd: emit string str=%.*s, length=%zu, huffman=%d, "
1003
0
         "encoded_length=%zu\n",
1004
0
         (int)len, (const char *)str, len, huffman, enclen);
1005
1006
0
  if (sizeof(sb) < blocklen) {
1007
0
    return NGHTTP2_ERR_HEADER_COMP;
1008
0
  }
1009
1010
0
  bufp = sb;
1011
0
  *bufp = huffman ? 1 << 7 : 0;
1012
0
  encode_length(bufp, enclen, 7);
1013
1014
0
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
1015
0
  if (rv != 0) {
1016
0
    return rv;
1017
0
  }
1018
1019
0
  if (huffman) {
1020
0
    rv = nghttp2_hd_huff_encode(bufs, str, len);
1021
0
  } else {
1022
0
    assert(enclen == len);
1023
0
    rv = nghttp2_bufs_add(bufs, str, len);
1024
0
  }
1025
1026
0
  return rv;
1027
0
}
1028
1029
0
static uint8_t pack_first_byte(int indexing_mode) {
1030
0
  switch (indexing_mode) {
1031
0
  case NGHTTP2_HD_WITH_INDEXING:
1032
0
    return 0x40u;
1033
0
  case NGHTTP2_HD_WITHOUT_INDEXING:
1034
0
    return 0;
1035
0
  case NGHTTP2_HD_NEVER_INDEXING:
1036
0
    return 0x10u;
1037
0
  default:
1038
0
    assert(0);
1039
0
  }
1040
  /* This is required to compile with android NDK r10d +
1041
     --enable-werror */
1042
0
  return 0;
1043
0
}
1044
1045
static int emit_indname_block(nghttp2_bufs *bufs, size_t idx,
1046
0
                              const nghttp2_nv *nv, int indexing_mode) {
1047
0
  int rv;
1048
0
  uint8_t *bufp;
1049
0
  size_t blocklen;
1050
0
  uint8_t sb[16];
1051
0
  size_t prefixlen;
1052
1053
0
  if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1054
0
    prefixlen = 6;
1055
0
  } else {
1056
0
    prefixlen = 4;
1057
0
  }
1058
1059
0
  DEBUGF("deflatehd: emit indname index=%zu, valuelen=%zu, indexing_mode=%d\n",
1060
0
         idx, nv->valuelen, indexing_mode);
1061
1062
0
  blocklen = count_encoded_length(idx + 1, prefixlen);
1063
1064
0
  if (sizeof(sb) < blocklen) {
1065
0
    return NGHTTP2_ERR_HEADER_COMP;
1066
0
  }
1067
1068
0
  bufp = sb;
1069
1070
0
  *bufp = pack_first_byte(indexing_mode);
1071
1072
0
  encode_length(bufp, idx + 1, prefixlen);
1073
1074
0
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
1075
0
  if (rv != 0) {
1076
0
    return rv;
1077
0
  }
1078
1079
0
  rv = emit_string(bufs, nv->value, nv->valuelen);
1080
0
  if (rv != 0) {
1081
0
    return rv;
1082
0
  }
1083
1084
0
  return 0;
1085
0
}
1086
1087
static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
1088
0
                              int indexing_mode) {
1089
0
  int rv;
1090
1091
0
  DEBUGF(
1092
0
    "deflatehd: emit newname namelen=%zu, valuelen=%zu, indexing_mode=%d\n",
1093
0
    nv->namelen, nv->valuelen, indexing_mode);
1094
1095
0
  rv = nghttp2_bufs_addb(bufs, pack_first_byte(indexing_mode));
1096
0
  if (rv != 0) {
1097
0
    return rv;
1098
0
  }
1099
1100
0
  rv = emit_string(bufs, nv->name, nv->namelen);
1101
0
  if (rv != 0) {
1102
0
    return rv;
1103
0
  }
1104
1105
0
  rv = emit_string(bufs, nv->value, nv->valuelen);
1106
0
  if (rv != 0) {
1107
0
    return rv;
1108
0
  }
1109
1110
0
  return 0;
1111
0
}
1112
1113
static int add_hd_table_incremental(nghttp2_hd_context *context,
1114
                                    nghttp2_hd_nv *nv, nghttp2_hd_map *map,
1115
14.4k
                                    uint32_t hash) {
1116
14.4k
  int rv;
1117
14.4k
  nghttp2_hd_entry *new_ent;
1118
14.4k
  size_t room;
1119
14.4k
  nghttp2_mem *mem;
1120
1121
14.4k
  mem = context->mem;
1122
14.4k
  room = entry_room(nv->name->len, nv->value->len);
1123
1124
15.5k
  while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
1125
15.5k
         context->hd_table.len > 0) {
1126
1.04k
    size_t idx = context->hd_table.len - 1;
1127
1.04k
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1128
1129
1.04k
    context->hd_table_bufsize -=
1130
1.04k
      entry_room(ent->nv.name->len, ent->nv.value->len);
1131
1132
1.04k
    DEBUGF("hpack: remove item from header table: %s: %s\n",
1133
1.04k
           (char *)ent->nv.name->base, (char *)ent->nv.value->base);
1134
1135
1.04k
    hd_ringbuf_pop_back(&context->hd_table);
1136
1.04k
    if (map) {
1137
0
      hd_map_remove(map, ent);
1138
0
    }
1139
1140
1.04k
    nghttp2_hd_entry_free(ent);
1141
1.04k
    nghttp2_mem_free(mem, ent);
1142
1.04k
  }
1143
1144
14.4k
  if (room > context->hd_table_bufsize_max) {
1145
    /* The entry taking more than NGHTTP2_HD_MAX_BUFFER_SIZE is
1146
       immediately evicted.  So we don't allocate memory for it. */
1147
432
    return 0;
1148
432
  }
1149
1150
14.0k
  new_ent = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry));
1151
14.0k
  if (new_ent == NULL) {
1152
0
    return NGHTTP2_ERR_NOMEM;
1153
0
  }
1154
1155
14.0k
  nghttp2_hd_entry_init(new_ent, nv);
1156
1157
14.0k
  rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
1158
1159
14.0k
  if (rv != 0) {
1160
0
    nghttp2_hd_entry_free(new_ent);
1161
0
    nghttp2_mem_free(mem, new_ent);
1162
1163
0
    return rv;
1164
0
  }
1165
1166
14.0k
  new_ent->seq = context->next_seq++;
1167
14.0k
  new_ent->hash = hash;
1168
1169
14.0k
  if (map) {
1170
0
    hd_map_insert(map, new_ent);
1171
0
  }
1172
1173
14.0k
  context->hd_table_bufsize += room;
1174
1175
14.0k
  return 0;
1176
14.0k
}
1177
1178
typedef struct {
1179
  nghttp2_ssize index;
1180
  /* Nonzero if both name and value are matched. */
1181
  int name_value_match;
1182
} search_result;
1183
1184
static search_result search_static_table(const nghttp2_nv *nv, int32_t token,
1185
0
                                         int name_only) {
1186
0
  search_result res = {token, 0};
1187
0
  int i;
1188
0
  const nghttp2_hd_static_entry *ent;
1189
1190
0
  if (name_only) {
1191
0
    return res;
1192
0
  }
1193
1194
0
  for (i = token;
1195
0
       i <= NGHTTP2_TOKEN_WWW_AUTHENTICATE && static_table[i].token == token;
1196
0
       ++i) {
1197
0
    ent = &static_table[i];
1198
0
    if (ent->value.len == nv->valuelen &&
1199
0
        memcmp(ent->value.base, nv->value, nv->valuelen) == 0) {
1200
0
      res.index = i;
1201
0
      res.name_value_match = 1;
1202
0
      return res;
1203
0
    }
1204
0
  }
1205
0
  return res;
1206
0
}
1207
1208
static search_result search_hd_table(nghttp2_hd_context *context,
1209
                                     const nghttp2_nv *nv, int32_t token,
1210
                                     int indexing_mode, nghttp2_hd_map *map,
1211
0
                                     uint32_t hash) {
1212
0
  search_result res = {-1, 0};
1213
0
  const nghttp2_hd_entry *ent;
1214
0
  int exact_match;
1215
0
  int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING;
1216
1217
0
  exact_match = 0;
1218
0
  ent = hd_map_find(map, &exact_match, nv, token, hash, name_only);
1219
1220
0
  if (!exact_match && token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1221
0
    return search_static_table(nv, token, name_only);
1222
0
  }
1223
1224
0
  if (ent == NULL) {
1225
0
    return res;
1226
0
  }
1227
1228
0
  res.index = (nghttp2_ssize)(context->next_seq - 1 - ent->seq +
1229
0
                              NGHTTP2_STATIC_TABLE_LENGTH);
1230
0
  res.name_value_match = exact_match;
1231
1232
0
  return res;
1233
0
}
1234
1235
static void hd_context_shrink_table_size(nghttp2_hd_context *context,
1236
2.15k
                                         nghttp2_hd_map *map) {
1237
2.15k
  nghttp2_mem *mem;
1238
1239
2.15k
  mem = context->mem;
1240
1241
2.51k
  while (context->hd_table_bufsize > context->hd_table_bufsize_max &&
1242
2.51k
         context->hd_table.len > 0) {
1243
361
    size_t idx = context->hd_table.len - 1;
1244
361
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1245
361
    context->hd_table_bufsize -=
1246
361
      entry_room(ent->nv.name->len, ent->nv.value->len);
1247
361
    hd_ringbuf_pop_back(&context->hd_table);
1248
361
    if (map) {
1249
0
      hd_map_remove(map, ent);
1250
0
    }
1251
1252
361
    nghttp2_hd_entry_free(ent);
1253
361
    nghttp2_mem_free(mem, ent);
1254
361
  }
1255
2.15k
}
1256
1257
int nghttp2_hd_deflate_change_table_size(
1258
613
  nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
1259
613
  size_t next_bufsize = nghttp2_min_size(
1260
613
    settings_max_dynamic_table_size, deflater->deflate_hd_table_bufsize_max);
1261
1262
613
  deflater->ctx.hd_table_bufsize_max = next_bufsize;
1263
1264
613
  deflater->min_hd_table_bufsize_max =
1265
613
    nghttp2_min_size(deflater->min_hd_table_bufsize_max, next_bufsize);
1266
1267
613
  deflater->notify_table_size_change = 1;
1268
1269
613
  hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
1270
613
  return 0;
1271
613
}
1272
1273
int nghttp2_hd_inflate_change_table_size(
1274
0
  nghttp2_hd_inflater *inflater, size_t settings_max_dynamic_table_size) {
1275
0
  switch (inflater->state) {
1276
0
  case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1277
0
  case NGHTTP2_HD_STATE_INFLATE_START:
1278
0
    break;
1279
0
  default:
1280
0
    return NGHTTP2_ERR_INVALID_STATE;
1281
0
  }
1282
1283
0
  inflater->settings_hd_table_bufsize_max = settings_max_dynamic_table_size;
1284
1285
  /* It seems that encoder is not required to send dynamic table size
1286
     update if the table size is not changed after applying
1287
     SETTINGS_HEADER_TABLE_SIZE.  RFC 7541 is ambiguous here, but this
1288
     is the intention of the editor.  If new maximum table size is
1289
     strictly smaller than the current negotiated maximum size,
1290
     encoder must send dynamic table size update.  In other cases, we
1291
     cannot expect it to do so. */
1292
0
  if (inflater->ctx.hd_table_bufsize_max > settings_max_dynamic_table_size) {
1293
0
    inflater->state = NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE;
1294
    /* Remember minimum value, and validate that encoder sends the
1295
       value less than or equal to this. */
1296
0
    inflater->min_hd_table_bufsize_max = settings_max_dynamic_table_size;
1297
1298
0
    inflater->ctx.hd_table_bufsize_max = settings_max_dynamic_table_size;
1299
1300
0
    hd_context_shrink_table_size(&inflater->ctx, NULL);
1301
0
  }
1302
1303
0
  return 0;
1304
0
}
1305
1306
#define INDEX_RANGE_VALID(context, idx)                                        \
1307
0
  ((idx) < (context)->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH)
1308
1309
59.2k
static size_t get_max_index(nghttp2_hd_context *context) {
1310
59.2k
  return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH;
1311
59.2k
}
1312
1313
58.2k
nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
1314
58.2k
  assert(INDEX_RANGE_VALID(context, idx));
1315
58.2k
  if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1316
46.6k
    return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
1317
46.6k
      ->nv;
1318
46.6k
  } else {
1319
11.5k
    const nghttp2_hd_static_entry *ent = &static_table[idx];
1320
11.5k
    nghttp2_hd_nv nv = {(nghttp2_rcbuf *)&ent->name,
1321
11.5k
                        (nghttp2_rcbuf *)&ent->value, ent->token,
1322
11.5k
                        NGHTTP2_NV_FLAG_NONE};
1323
11.5k
    return nv;
1324
11.5k
  }
1325
58.2k
}
1326
1327
static const nghttp2_nv *nghttp2_hd_table_get2(nghttp2_hd_context *context,
1328
0
                                               size_t idx) {
1329
0
  assert(INDEX_RANGE_VALID(context, idx));
1330
0
  if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1331
0
    return &hd_ringbuf_get(&context->hd_table,
1332
0
                           idx - NGHTTP2_STATIC_TABLE_LENGTH)
1333
0
              ->cnv;
1334
0
  }
1335
1336
0
  return &static_table[idx].cnv;
1337
0
}
1338
1339
static int hd_deflate_decide_indexing(nghttp2_hd_deflater *deflater,
1340
0
                                      const nghttp2_nv *nv, int32_t token) {
1341
0
  if (token == NGHTTP2_TOKEN__PATH || token == NGHTTP2_TOKEN_AGE ||
1342
0
      token == NGHTTP2_TOKEN_CONTENT_LENGTH || token == NGHTTP2_TOKEN_ETAG ||
1343
0
      token == NGHTTP2_TOKEN_IF_MODIFIED_SINCE ||
1344
0
      token == NGHTTP2_TOKEN_IF_NONE_MATCH || token == NGHTTP2_TOKEN_LOCATION ||
1345
0
      token == NGHTTP2_TOKEN_SET_COOKIE ||
1346
0
      entry_room(nv->namelen, nv->valuelen) >
1347
0
        deflater->ctx.hd_table_bufsize_max * 3 / 4) {
1348
0
    return NGHTTP2_HD_WITHOUT_INDEXING;
1349
0
  }
1350
1351
0
  return NGHTTP2_HD_WITH_INDEXING;
1352
0
}
1353
1354
static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
1355
0
                      const nghttp2_nv *nv) {
1356
0
  int rv;
1357
0
  search_result res;
1358
0
  nghttp2_ssize idx;
1359
0
  int indexing_mode;
1360
0
  int32_t token;
1361
0
  nghttp2_mem *mem;
1362
0
  uint32_t hash = 0;
1363
1364
0
  DEBUGF("deflatehd: deflating %.*s: %.*s\n", (int)nv->namelen, nv->name,
1365
0
         (int)nv->valuelen, nv->value);
1366
1367
0
  mem = deflater->ctx.mem;
1368
1369
0
  token = lookup_token(nv->name, nv->namelen);
1370
0
  if (token == -1) {
1371
0
    hash = name_hash(nv);
1372
0
  } else if (token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1373
0
    hash = static_table[token].hash;
1374
0
  }
1375
1376
  /* Don't index authorization header field since it may contain low
1377
     entropy secret data (e.g., id/password).  Also cookie header
1378
     field with less than 20 bytes value is also never indexed.  This
1379
     is the same criteria used in Firefox codebase. */
1380
0
  indexing_mode = token == NGHTTP2_TOKEN_AUTHORIZATION ||
1381
0
                      (token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) ||
1382
0
                      (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX)
1383
0
                    ? NGHTTP2_HD_NEVER_INDEXING
1384
0
                    : hd_deflate_decide_indexing(deflater, nv, token);
1385
1386
0
  res = search_hd_table(&deflater->ctx, nv, token, indexing_mode,
1387
0
                        &deflater->map, hash);
1388
1389
0
  idx = res.index;
1390
1391
0
  if (res.name_value_match) {
1392
0
    DEBUGF("deflatehd: name/value match index=%td\n", idx);
1393
1394
0
    rv = emit_indexed_block(bufs, (size_t)idx);
1395
0
    if (rv != 0) {
1396
0
      return rv;
1397
0
    }
1398
1399
0
    return 0;
1400
0
  }
1401
1402
0
  if (res.index != -1) {
1403
0
    DEBUGF("deflatehd: name match index=%td\n", res.index);
1404
0
  }
1405
1406
0
  if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1407
0
    nghttp2_hd_nv hd_nv;
1408
1409
0
    if (idx != -1) {
1410
0
      hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name;
1411
0
      nghttp2_rcbuf_incref(hd_nv.name);
1412
0
    } else {
1413
0
      rv = nghttp2_rcbuf_new2(&hd_nv.name, nv->name, nv->namelen, mem);
1414
0
      if (rv != 0) {
1415
0
        return rv;
1416
0
      }
1417
0
    }
1418
1419
0
    rv = nghttp2_rcbuf_new2(&hd_nv.value, nv->value, nv->valuelen, mem);
1420
1421
0
    if (rv != 0) {
1422
0
      nghttp2_rcbuf_decref(hd_nv.name);
1423
0
      return rv;
1424
0
    }
1425
1426
0
    hd_nv.token = token;
1427
0
    hd_nv.flags = NGHTTP2_NV_FLAG_NONE;
1428
1429
0
    rv = add_hd_table_incremental(&deflater->ctx, &hd_nv, &deflater->map, hash);
1430
1431
0
    nghttp2_rcbuf_decref(hd_nv.value);
1432
0
    nghttp2_rcbuf_decref(hd_nv.name);
1433
1434
0
    if (rv != 0) {
1435
0
      return NGHTTP2_ERR_HEADER_COMP;
1436
0
    }
1437
0
  }
1438
0
  if (idx == -1) {
1439
0
    rv = emit_newname_block(bufs, nv, indexing_mode);
1440
0
  } else {
1441
0
    rv = emit_indname_block(bufs, (size_t)idx, nv, indexing_mode);
1442
0
  }
1443
0
  if (rv != 0) {
1444
0
    return rv;
1445
0
  }
1446
1447
0
  return 0;
1448
0
}
1449
1450
int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
1451
                               nghttp2_bufs *bufs, const nghttp2_nv *nv,
1452
0
                               size_t nvlen) {
1453
0
  size_t i;
1454
0
  int rv = 0;
1455
1456
0
  if (deflater->ctx.bad) {
1457
0
    return NGHTTP2_ERR_HEADER_COMP;
1458
0
  }
1459
1460
0
  if (deflater->notify_table_size_change) {
1461
0
    size_t min_hd_table_bufsize_max;
1462
1463
0
    min_hd_table_bufsize_max = deflater->min_hd_table_bufsize_max;
1464
1465
0
    deflater->notify_table_size_change = 0;
1466
0
    deflater->min_hd_table_bufsize_max = UINT32_MAX;
1467
1468
0
    if (deflater->ctx.hd_table_bufsize_max > min_hd_table_bufsize_max) {
1469
0
      rv = emit_table_size(bufs, min_hd_table_bufsize_max);
1470
1471
0
      if (rv != 0) {
1472
0
        goto fail;
1473
0
      }
1474
0
    }
1475
1476
0
    rv = emit_table_size(bufs, deflater->ctx.hd_table_bufsize_max);
1477
1478
0
    if (rv != 0) {
1479
0
      goto fail;
1480
0
    }
1481
0
  }
1482
1483
0
  for (i = 0; i < nvlen; ++i) {
1484
0
    rv = deflate_nv(deflater, bufs, &nv[i]);
1485
0
    if (rv != 0) {
1486
0
      goto fail;
1487
0
    }
1488
0
  }
1489
1490
0
  DEBUGF("deflatehd: all input name/value pairs were deflated\n");
1491
1492
0
  return 0;
1493
0
fail:
1494
0
  DEBUGF("deflatehd: error return %d\n", rv);
1495
1496
0
  deflater->ctx.bad = 1;
1497
0
  return rv;
1498
0
}
1499
1500
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
1501
                              size_t buflen, const nghttp2_nv *nv,
1502
0
                              size_t nvlen) {
1503
0
  return (ssize_t)nghttp2_hd_deflate_hd2(deflater, buf, buflen, nv, nvlen);
1504
0
}
1505
1506
nghttp2_ssize nghttp2_hd_deflate_hd2(nghttp2_hd_deflater *deflater,
1507
                                     uint8_t *buf, size_t buflen,
1508
0
                                     const nghttp2_nv *nv, size_t nvlen) {
1509
0
  nghttp2_bufs bufs;
1510
0
  int rv;
1511
0
  nghttp2_mem *mem;
1512
1513
0
  mem = deflater->ctx.mem;
1514
1515
0
  rv = nghttp2_bufs_wrap_init(&bufs, buf, buflen, mem);
1516
1517
0
  if (rv != 0) {
1518
0
    return rv;
1519
0
  }
1520
1521
0
  rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nv, nvlen);
1522
1523
0
  buflen = nghttp2_bufs_len(&bufs);
1524
1525
0
  nghttp2_bufs_wrap_free(&bufs);
1526
1527
0
  if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
1528
0
    return NGHTTP2_ERR_INSUFF_BUFSIZE;
1529
0
  }
1530
1531
0
  if (rv != 0) {
1532
0
    return rv;
1533
0
  }
1534
1535
0
  return (nghttp2_ssize)buflen;
1536
0
}
1537
1538
ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
1539
                                  const nghttp2_vec *vec, size_t veclen,
1540
0
                                  const nghttp2_nv *nv, size_t nvlen) {
1541
0
  return (ssize_t)nghttp2_hd_deflate_hd_vec2(deflater, vec, veclen, nv, nvlen);
1542
0
}
1543
1544
nghttp2_ssize nghttp2_hd_deflate_hd_vec2(nghttp2_hd_deflater *deflater,
1545
                                         const nghttp2_vec *vec, size_t veclen,
1546
0
                                         const nghttp2_nv *nv, size_t nvlen) {
1547
0
  nghttp2_bufs bufs;
1548
0
  int rv;
1549
0
  nghttp2_mem *mem;
1550
0
  size_t buflen;
1551
1552
0
  mem = deflater->ctx.mem;
1553
1554
0
  rv = nghttp2_bufs_wrap_init2(&bufs, vec, veclen, mem);
1555
1556
0
  if (rv != 0) {
1557
0
    return rv;
1558
0
  }
1559
1560
0
  rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nv, nvlen);
1561
1562
0
  buflen = nghttp2_bufs_len(&bufs);
1563
1564
0
  nghttp2_bufs_wrap_free(&bufs);
1565
1566
0
  if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
1567
0
    return NGHTTP2_ERR_INSUFF_BUFSIZE;
1568
0
  }
1569
1570
0
  if (rv != 0) {
1571
0
    return rv;
1572
0
  }
1573
1574
0
  return (nghttp2_ssize)buflen;
1575
0
}
1576
1577
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
1578
0
                                const nghttp2_nv *nva, size_t nvlen) {
1579
0
  size_t n = 0;
1580
0
  size_t i;
1581
0
  (void)deflater;
1582
1583
  /* Possible Maximum Header Table Size Change.  Encoding (1u << 31) -
1584
     1 using 4 bit prefix requires 6 bytes.  We may emit this at most
1585
     twice. */
1586
0
  n += 12;
1587
1588
  /* Use Literal Header Field without indexing - New Name, since it is
1589
     most space consuming format.  Also we choose the less one between
1590
     non-huffman and huffman, so using literal byte count is
1591
     sufficient for upper bound.
1592
1593
     Encoding (1u << 31) - 1 using 7 bit prefix requires 6 bytes.  We
1594
     need 2 of this for |nvlen| header fields. */
1595
0
  n += 6 * 2 * nvlen;
1596
1597
0
  for (i = 0; i < nvlen; ++i) {
1598
0
    n += nva[i].namelen + nva[i].valuelen;
1599
0
  }
1600
1601
0
  return n;
1602
0
}
1603
1604
int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
1605
0
                           size_t deflate_hd_table_bufsize_max) {
1606
0
  return nghttp2_hd_deflate_new2(deflater_ptr, deflate_hd_table_bufsize_max,
1607
0
                                 NULL);
1608
0
}
1609
1610
int nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr,
1611
                            size_t deflate_hd_table_bufsize_max,
1612
0
                            nghttp2_mem *mem) {
1613
0
  int rv;
1614
0
  nghttp2_hd_deflater *deflater;
1615
1616
0
  if (mem == NULL) {
1617
0
    mem = nghttp2_mem_default();
1618
0
  }
1619
1620
0
  deflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_deflater));
1621
1622
0
  if (deflater == NULL) {
1623
0
    return NGHTTP2_ERR_NOMEM;
1624
0
  }
1625
1626
0
  rv = nghttp2_hd_deflate_init2(deflater, deflate_hd_table_bufsize_max, mem);
1627
1628
0
  if (rv != 0) {
1629
0
    nghttp2_mem_free(mem, deflater);
1630
1631
0
    return rv;
1632
0
  }
1633
1634
0
  *deflater_ptr = deflater;
1635
1636
0
  return 0;
1637
0
}
1638
1639
0
void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater) {
1640
0
  nghttp2_mem *mem;
1641
1642
0
  mem = deflater->ctx.mem;
1643
1644
0
  nghttp2_hd_deflate_free(deflater);
1645
1646
0
  nghttp2_mem_free(mem, deflater);
1647
0
}
1648
1649
static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater,
1650
48.0k
                                           const uint8_t *in) {
1651
48.0k
  inflater->huffman_encoded = (*in & (1 << 7)) != 0;
1652
48.0k
}
1653
1654
/*
1655
 * Decodes the integer from the range [in, last).  The result is
1656
 * assigned to |inflater->left|.  If the |inflater->left| is 0, then
1657
 * it performs variable integer decoding from scratch. Otherwise, it
1658
 * uses the |inflater->left| as the initial value and continues to
1659
 * decode assuming that [in, last) begins with intermediary sequence.
1660
 *
1661
 * This function returns the number of bytes read if it succeeds, or
1662
 * one of the following negative error codes:
1663
 *
1664
 * NGHTTP2_ERR_HEADER_COMP
1665
 *   Integer decoding failed
1666
 */
1667
static nghttp2_ssize hd_inflate_read_len(nghttp2_hd_inflater *inflater,
1668
                                         int *rfin, const uint8_t *in,
1669
                                         const uint8_t *last, size_t prefix,
1670
109k
                                         size_t maxlen) {
1671
109k
  nghttp2_ssize rv;
1672
109k
  uint32_t out;
1673
1674
109k
  *rfin = 0;
1675
1676
109k
  rv = decode_length(&out, &inflater->shift, rfin, (uint32_t)inflater->left,
1677
109k
                     inflater->shift, in, last, prefix);
1678
1679
109k
  if (rv == -1) {
1680
94
    DEBUGF("inflatehd: integer decoding failed\n");
1681
94
    return NGHTTP2_ERR_HEADER_COMP;
1682
94
  }
1683
1684
109k
  if (out > maxlen) {
1685
732
    DEBUGF("inflatehd: integer exceeded the maximum value %zu\n", maxlen);
1686
732
    return NGHTTP2_ERR_HEADER_COMP;
1687
732
  }
1688
1689
108k
  inflater->left = out;
1690
1691
108k
  DEBUGF("inflatehd: decoded integer is %u\n", out);
1692
1693
108k
  return rv;
1694
109k
}
1695
1696
/*
1697
 * Reads |inflater->left| bytes from the range [in, last) and performs
1698
 * huffman decoding against them and pushes the result into the
1699
 * |buffer|.
1700
 *
1701
 * This function returns the number of bytes read if it succeeds, or
1702
 * one of the following negative error codes:
1703
 *
1704
 * NGHTTP2_ERR_NOMEM
1705
 *   Out of memory
1706
 * NGHTTP2_ERR_HEADER_COMP
1707
 *   Huffman decoding failed
1708
 */
1709
static nghttp2_ssize hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
1710
                                          nghttp2_buf *buf, const uint8_t *in,
1711
14.1k
                                          const uint8_t *last) {
1712
14.1k
  nghttp2_ssize readlen;
1713
14.1k
  int fin = 0;
1714
14.1k
  if ((size_t)(last - in) >= inflater->left) {
1715
14.0k
    last = in + inflater->left;
1716
14.0k
    fin = 1;
1717
14.0k
  }
1718
14.1k
  readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
1719
14.1k
                                   (size_t)(last - in), fin);
1720
1721
14.1k
  if (readlen < 0) {
1722
3
    DEBUGF("inflatehd: huffman decoding failed\n");
1723
3
    return readlen;
1724
3
  }
1725
14.1k
  if (nghttp2_hd_huff_decode_failure_state(&inflater->huff_decode_ctx)) {
1726
9
    DEBUGF("inflatehd: huffman decoding failed\n");
1727
9
    return NGHTTP2_ERR_HEADER_COMP;
1728
9
  }
1729
1730
14.1k
  inflater->left -= (size_t)readlen;
1731
14.1k
  return readlen;
1732
14.1k
}
1733
1734
/*
1735
 * Reads |inflater->left| bytes from the range [in, last) and copies
1736
 * them into the |buffer|.
1737
 *
1738
 * This function returns the number of bytes read if it succeeds, or
1739
 * one of the following negative error codes:
1740
 *
1741
 * NGHTTP2_ERR_NOMEM
1742
 *   Out of memory
1743
 * NGHTTP2_ERR_HEADER_COMP
1744
 *   Header decompression failed
1745
 */
1746
static nghttp2_ssize hd_inflate_read(nghttp2_hd_inflater *inflater,
1747
                                     nghttp2_buf *buf, const uint8_t *in,
1748
33.4k
                                     const uint8_t *last) {
1749
33.4k
  size_t len = nghttp2_min_size((size_t)(last - in), inflater->left);
1750
1751
33.4k
  buf->last = nghttp2_cpymem(buf->last, in, len);
1752
1753
33.4k
  inflater->left -= len;
1754
33.4k
  return (nghttp2_ssize)len;
1755
33.4k
}
1756
1757
/*
1758
 * Finalize indexed header representation reception.  The referenced
1759
 * header is always emitted, and |*nv_out| is filled with that value.
1760
 */
1761
static void hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
1762
49.4k
                                      nghttp2_hd_nv *nv_out) {
1763
49.4k
  nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1764
1765
49.4k
  emit_header(nv_out, &nv);
1766
49.4k
}
1767
1768
/*
1769
 * Finalize literal header representation - new name- reception. If
1770
 * header is emitted, |*nv_out| is filled with that value and 0 is
1771
 * returned.
1772
 *
1773
 * This function returns 0 if it succeeds, or one of the following
1774
 * negative error codes:
1775
 *
1776
 * NGHTTP2_ERR_NOMEM
1777
 *   Out of memory
1778
 */
1779
static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
1780
19.2k
                                     nghttp2_hd_nv *nv_out) {
1781
19.2k
  nghttp2_hd_nv nv;
1782
19.2k
  int rv;
1783
1784
19.2k
  if (inflater->no_index) {
1785
706
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1786
18.5k
  } else {
1787
18.5k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1788
18.5k
  }
1789
1790
19.2k
  nv.name = inflater->namercbuf;
1791
19.2k
  nv.value = inflater->valuercbuf;
1792
19.2k
  nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len);
1793
1794
19.2k
  if (inflater->index_required) {
1795
7.64k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1796
1797
7.64k
    if (rv != 0) {
1798
0
      return rv;
1799
0
    }
1800
7.64k
  }
1801
1802
19.2k
  emit_header(nv_out, &nv);
1803
1804
19.2k
  inflater->nv_name_keep = nv.name;
1805
19.2k
  inflater->nv_value_keep = nv.value;
1806
1807
19.2k
  inflater->namercbuf = NULL;
1808
19.2k
  inflater->valuercbuf = NULL;
1809
1810
19.2k
  return 0;
1811
19.2k
}
1812
1813
/*
1814
 * Finalize literal header representation - indexed name-
1815
 * reception. If header is emitted, |*nv_out| is filled with that
1816
 * value and 0 is returned.
1817
 *
1818
 * This function returns 0 if it succeeds, or one of the following
1819
 * negative error codes:
1820
 *
1821
 * NGHTTP2_ERR_NOMEM
1822
 *   Out of memory
1823
 */
1824
static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
1825
8.84k
                                     nghttp2_hd_nv *nv_out) {
1826
8.84k
  nghttp2_hd_nv nv;
1827
8.84k
  int rv;
1828
1829
8.84k
  nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1830
1831
8.84k
  if (inflater->no_index) {
1832
332
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1833
8.51k
  } else {
1834
8.51k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1835
8.51k
  }
1836
1837
8.84k
  nghttp2_rcbuf_incref(nv.name);
1838
1839
8.84k
  nv.value = inflater->valuercbuf;
1840
1841
8.84k
  if (inflater->index_required) {
1842
6.84k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1843
6.84k
    if (rv != 0) {
1844
0
      nghttp2_rcbuf_decref(nv.name);
1845
0
      return NGHTTP2_ERR_NOMEM;
1846
0
    }
1847
6.84k
  }
1848
1849
8.84k
  emit_header(nv_out, &nv);
1850
1851
8.84k
  inflater->nv_name_keep = nv.name;
1852
8.84k
  inflater->nv_value_keep = nv.value;
1853
1854
8.84k
  inflater->valuercbuf = NULL;
1855
1856
8.84k
  return 0;
1857
8.84k
}
1858
1859
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
1860
                              int *inflate_flags, uint8_t *in, size_t inlen,
1861
0
                              int in_final) {
1862
0
  return nghttp2_hd_inflate_hd2(inflater, nv_out, inflate_flags, in, inlen,
1863
0
                                in_final);
1864
0
}
1865
1866
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
1867
                               nghttp2_nv *nv_out, int *inflate_flags,
1868
0
                               const uint8_t *in, size_t inlen, int in_final) {
1869
0
  return (nghttp2_ssize)nghttp2_hd_inflate_hd3(inflater, nv_out, inflate_flags,
1870
0
                                               in, inlen, in_final);
1871
0
}
1872
1873
nghttp2_ssize nghttp2_hd_inflate_hd3(nghttp2_hd_inflater *inflater,
1874
                                     nghttp2_nv *nv_out, int *inflate_flags,
1875
                                     const uint8_t *in, size_t inlen,
1876
0
                                     int in_final) {
1877
0
  nghttp2_ssize rv;
1878
0
  nghttp2_hd_nv hd_nv;
1879
1880
0
  rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
1881
0
                                in_final);
1882
1883
0
  if (rv < 0) {
1884
0
    return rv;
1885
0
  }
1886
1887
0
  if (*inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
1888
0
    nv_out->name = hd_nv.name->base;
1889
0
    nv_out->namelen = hd_nv.name->len;
1890
1891
0
    nv_out->value = hd_nv.value->base;
1892
0
    nv_out->valuelen = hd_nv.value->len;
1893
1894
0
    nv_out->flags = hd_nv.flags;
1895
0
  }
1896
1897
0
  return rv;
1898
0
}
1899
1900
nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
1901
                                       nghttp2_hd_nv *nv_out,
1902
                                       int *inflate_flags, const uint8_t *in,
1903
107k
                                       size_t inlen, int in_final) {
1904
107k
  nghttp2_ssize rv = 0;
1905
107k
  const uint8_t *first = in;
1906
107k
  const uint8_t *last = in + inlen;
1907
107k
  int rfin = 0;
1908
107k
  int busy = 0;
1909
107k
  nghttp2_mem *mem;
1910
1911
107k
  mem = inflater->ctx.mem;
1912
1913
107k
  if (inflater->ctx.bad) {
1914
0
    return NGHTTP2_ERR_HEADER_COMP;
1915
0
  }
1916
1917
107k
  DEBUGF("inflatehd: start state=%d\n", inflater->state);
1918
107k
  hd_inflate_keep_free(inflater);
1919
107k
  *inflate_flags = NGHTTP2_HD_INFLATE_NONE;
1920
265k
  for (; in != last || busy;) {
1921
237k
    busy = 0;
1922
237k
    switch (inflater->state) {
1923
0
    case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1924
0
      if ((*in & 0xe0u) != 0x20u) {
1925
0
        DEBUGF("inflatehd: header table size change was expected, but saw "
1926
0
               "0x%02x as first byte",
1927
0
               *in);
1928
0
        rv = NGHTTP2_ERR_HEADER_COMP;
1929
0
        goto fail;
1930
0
      }
1931
    /* fall through */
1932
29.3k
    case NGHTTP2_HD_STATE_INFLATE_START:
1933
80.5k
    case NGHTTP2_HD_STATE_OPCODE:
1934
80.5k
      if ((*in & 0xe0u) == 0x20u) {
1935
1.78k
        DEBUGF("inflatehd: header table size change\n");
1936
1.78k
        if (inflater->state == NGHTTP2_HD_STATE_OPCODE) {
1937
24
          DEBUGF("inflatehd: header table size change must appear at the head "
1938
24
                 "of header block\n");
1939
24
          rv = NGHTTP2_ERR_HEADER_COMP;
1940
24
          goto fail;
1941
24
        }
1942
1.75k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1943
1.75k
        inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
1944
78.7k
      } else if (*in & 0x80u) {
1945
49.6k
        DEBUGF("inflatehd: indexed repr\n");
1946
49.6k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1947
49.6k
        inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1948
49.6k
      } else {
1949
29.1k
        if (*in == 0x40u || *in == 0 || *in == 0x10u) {
1950
19.6k
          DEBUGF("inflatehd: literal header repr - new name\n");
1951
19.6k
          inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
1952
19.6k
          inflater->state = NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN;
1953
19.6k
        } else {
1954
9.42k
          DEBUGF("inflatehd: literal header repr - indexed name\n");
1955
9.42k
          inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
1956
9.42k
          inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1957
9.42k
        }
1958
29.1k
        inflater->index_required = (*in & 0x40) != 0;
1959
29.1k
        inflater->no_index = (*in & 0xf0u) == 0x10u;
1960
29.1k
        DEBUGF("inflatehd: indexing required=%d, no_index=%d\n",
1961
29.1k
               inflater->index_required, inflater->no_index);
1962
29.1k
        if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1963
19.6k
          ++in;
1964
19.6k
        }
1965
29.1k
      }
1966
80.4k
      inflater->left = 0;
1967
80.4k
      inflater->shift = 0;
1968
80.4k
      break;
1969
2.03k
    case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
1970
2.03k
      rfin = 0;
1971
2.03k
      rv = hd_inflate_read_len(
1972
2.03k
        inflater, &rfin, in, last, 5,
1973
2.03k
        nghttp2_min_size(inflater->min_hd_table_bufsize_max,
1974
2.03k
                         inflater->settings_hd_table_bufsize_max));
1975
2.03k
      if (rv < 0) {
1976
176
        goto fail;
1977
176
      }
1978
1.86k
      in += rv;
1979
1.86k
      if (!rfin) {
1980
324
        goto almost_ok;
1981
324
      }
1982
1.53k
      DEBUGF("inflatehd: table_size=%zu\n", inflater->left);
1983
1.53k
      inflater->min_hd_table_bufsize_max = UINT32_MAX;
1984
1.53k
      inflater->ctx.hd_table_bufsize_max = inflater->left;
1985
1.53k
      hd_context_shrink_table_size(&inflater->ctx, NULL);
1986
1.53k
      inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
1987
1.53k
      break;
1988
59.2k
    case NGHTTP2_HD_STATE_READ_INDEX: {
1989
59.2k
      size_t prefixlen;
1990
1991
59.2k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
1992
49.6k
        prefixlen = 7;
1993
49.6k
      } else if (inflater->index_required) {
1994
7.08k
        prefixlen = 6;
1995
7.08k
      } else {
1996
2.56k
        prefixlen = 4;
1997
2.56k
      }
1998
1999
59.2k
      rfin = 0;
2000
59.2k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
2001
59.2k
                               get_max_index(&inflater->ctx));
2002
59.2k
      if (rv < 0) {
2003
320
        goto fail;
2004
320
      }
2005
2006
58.9k
      in += rv;
2007
2008
58.9k
      if (!rfin) {
2009
248
        goto almost_ok;
2010
248
      }
2011
2012
58.7k
      if (inflater->left == 0) {
2013
13
        rv = NGHTTP2_ERR_HEADER_COMP;
2014
13
        goto fail;
2015
13
      }
2016
2017
58.7k
      DEBUGF("inflatehd: index=%zu\n", inflater->left);
2018
58.7k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
2019
49.4k
        inflater->index = inflater->left;
2020
49.4k
        --inflater->index;
2021
2022
49.4k
        hd_inflate_commit_indexed(inflater, nv_out);
2023
2024
49.4k
        inflater->state = NGHTTP2_HD_STATE_OPCODE;
2025
49.4k
        *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2026
49.4k
        return (nghttp2_ssize)(in - first);
2027
49.4k
      } else {
2028
9.28k
        inflater->index = inflater->left;
2029
9.28k
        --inflater->index;
2030
2031
9.28k
        inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2032
9.28k
      }
2033
9.28k
      break;
2034
58.7k
    }
2035
19.6k
    case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
2036
19.6k
      hd_inflate_set_huffman_encoded(inflater, in);
2037
19.6k
      inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
2038
19.6k
      inflater->left = 0;
2039
19.6k
      inflater->shift = 0;
2040
19.6k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2041
    /* Fall through */
2042
19.7k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN:
2043
19.7k
      rfin = 0;
2044
19.7k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2045
19.7k
      if (rv < 0) {
2046
164
        goto fail;
2047
164
      }
2048
19.5k
      in += rv;
2049
19.5k
      if (!rfin) {
2050
171
        DEBUGF("inflatehd: integer not fully decoded. current=%zu\n",
2051
171
               inflater->left);
2052
2053
171
        goto almost_ok;
2054
171
      }
2055
2056
19.4k
      if (inflater->huffman_encoded) {
2057
7.74k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2058
2059
7.74k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
2060
2061
7.74k
        rv =
2062
7.74k
          nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1, mem);
2063
11.6k
      } else {
2064
11.6k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
2065
11.6k
        rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
2066
11.6k
      }
2067
2068
19.4k
      if (rv != 0) {
2069
0
        goto fail;
2070
0
      }
2071
2072
19.4k
      nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base,
2073
19.4k
                            inflater->namercbuf->len);
2074
2075
19.4k
      break;
2076
7.71k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
2077
7.71k
      rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
2078
7.71k
      if (rv < 0) {
2079
6
        goto fail;
2080
6
      }
2081
2082
7.70k
      in += rv;
2083
2084
7.70k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2085
2086
7.70k
      if (inflater->left) {
2087
58
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2088
2089
58
        goto almost_ok;
2090
58
      }
2091
2092
7.64k
      *inflater->namebuf.last = '\0';
2093
7.64k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2094
2095
7.64k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2096
2097
7.64k
      break;
2098
11.6k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
2099
11.6k
      rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
2100
11.6k
      if (rv < 0) {
2101
0
        goto fail;
2102
0
      }
2103
2104
11.6k
      in += rv;
2105
2106
11.6k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2107
11.6k
      if (inflater->left) {
2108
51
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2109
2110
51
        goto almost_ok;
2111
51
      }
2112
2113
11.5k
      *inflater->namebuf.last = '\0';
2114
11.5k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2115
2116
11.5k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2117
2118
11.5k
      break;
2119
28.4k
    case NGHTTP2_HD_STATE_CHECK_VALUELEN:
2120
28.4k
      hd_inflate_set_huffman_encoded(inflater, in);
2121
28.4k
      inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
2122
28.4k
      inflater->left = 0;
2123
28.4k
      inflater->shift = 0;
2124
28.4k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2125
    /* Fall through */
2126
28.5k
    case NGHTTP2_HD_STATE_READ_VALUELEN:
2127
28.5k
      rfin = 0;
2128
28.5k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2129
28.5k
      if (rv < 0) {
2130
166
        goto fail;
2131
166
      }
2132
2133
28.3k
      in += rv;
2134
2135
28.3k
      if (!rfin) {
2136
152
        goto almost_ok;
2137
152
      }
2138
2139
28.2k
      DEBUGF("inflatehd: valuelen=%zu\n", inflater->left);
2140
2141
28.2k
      if (inflater->huffman_encoded) {
2142
6.45k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2143
2144
6.45k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
2145
2146
6.45k
        rv =
2147
6.45k
          nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1, mem);
2148
21.7k
      } else {
2149
21.7k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
2150
2151
21.7k
        rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem);
2152
21.7k
      }
2153
2154
28.2k
      if (rv != 0) {
2155
0
        goto fail;
2156
0
      }
2157
2158
28.2k
      nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base,
2159
28.2k
                            inflater->valuercbuf->len);
2160
2161
28.2k
      busy = 1;
2162
2163
28.2k
      break;
2164
6.46k
    case NGHTTP2_HD_STATE_READ_VALUEHUFF:
2165
6.46k
      rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
2166
6.46k
      if (rv < 0) {
2167
6
        goto fail;
2168
6
      }
2169
2170
6.45k
      in += rv;
2171
2172
6.45k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2173
2174
6.45k
      if (inflater->left) {
2175
88
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2176
2177
88
        goto almost_ok;
2178
88
      }
2179
2180
6.36k
      *inflater->valuebuf.last = '\0';
2181
6.36k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2182
2183
6.36k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2184
3.45k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2185
3.45k
      } else {
2186
2.91k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2187
2.91k
      }
2188
2189
6.36k
      if (rv != 0) {
2190
0
        goto fail;
2191
0
      }
2192
2193
6.36k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2194
6.36k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2195
2196
6.36k
      return (nghttp2_ssize)(in - first);
2197
21.7k
    case NGHTTP2_HD_STATE_READ_VALUE:
2198
21.7k
      rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
2199
21.7k
      if (rv < 0) {
2200
0
        DEBUGF("inflatehd: value read failure %td: %s\n", rv,
2201
0
               nghttp2_strerror((int)rv));
2202
0
        goto fail;
2203
0
      }
2204
2205
21.7k
      in += rv;
2206
2207
21.7k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2208
2209
21.7k
      if (inflater->left) {
2210
84
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2211
84
        goto almost_ok;
2212
84
      }
2213
2214
21.6k
      *inflater->valuebuf.last = '\0';
2215
21.6k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2216
2217
21.6k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2218
15.7k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2219
15.7k
      } else {
2220
5.92k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2221
5.92k
      }
2222
2223
21.6k
      if (rv != 0) {
2224
0
        goto fail;
2225
0
      }
2226
2227
21.6k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2228
21.6k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2229
2230
21.6k
      return (nghttp2_ssize)(in - first);
2231
237k
    }
2232
237k
  }
2233
2234
27.6k
  assert(in == last);
2235
2236
27.6k
  DEBUGF("inflatehd: all input bytes were processed\n");
2237
2238
27.6k
  if (in_final) {
2239
22.7k
    DEBUGF("inflatehd: in_final set\n");
2240
2241
22.7k
    if (inflater->state != NGHTTP2_HD_STATE_OPCODE &&
2242
22.7k
        inflater->state != NGHTTP2_HD_STATE_INFLATE_START) {
2243
24
      DEBUGF("inflatehd: unacceptable state=%d\n", inflater->state);
2244
24
      rv = NGHTTP2_ERR_HEADER_COMP;
2245
2246
24
      goto fail;
2247
24
    }
2248
22.7k
    *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
2249
22.7k
  }
2250
27.6k
  return (nghttp2_ssize)(in - first);
2251
2252
1.17k
almost_ok:
2253
1.17k
  if (in_final) {
2254
8
    DEBUGF("inflatehd: input ended prematurely\n");
2255
2256
8
    rv = NGHTTP2_ERR_HEADER_COMP;
2257
2258
8
    goto fail;
2259
8
  }
2260
1.16k
  return (nghttp2_ssize)(in - first);
2261
2262
907
fail:
2263
907
  DEBUGF("inflatehd: error return %td\n", rv);
2264
2265
907
  inflater->ctx.bad = 1;
2266
907
  return rv;
2267
1.17k
}
2268
2269
22.7k
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
2270
22.7k
  hd_inflate_keep_free(inflater);
2271
22.7k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
2272
22.7k
  return 0;
2273
22.7k
}
2274
2275
0
int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr) {
2276
0
  return nghttp2_hd_inflate_new2(inflater_ptr, NULL);
2277
0
}
2278
2279
int nghttp2_hd_inflate_new2(nghttp2_hd_inflater **inflater_ptr,
2280
0
                            nghttp2_mem *mem) {
2281
0
  int rv;
2282
0
  nghttp2_hd_inflater *inflater;
2283
2284
0
  if (mem == NULL) {
2285
0
    mem = nghttp2_mem_default();
2286
0
  }
2287
2288
0
  inflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_inflater));
2289
2290
0
  if (inflater == NULL) {
2291
0
    return NGHTTP2_ERR_NOMEM;
2292
0
  }
2293
2294
0
  rv = nghttp2_hd_inflate_init(inflater, mem);
2295
2296
0
  if (rv != 0) {
2297
0
    nghttp2_mem_free(mem, inflater);
2298
2299
0
    return rv;
2300
0
  }
2301
2302
0
  *inflater_ptr = inflater;
2303
2304
0
  return 0;
2305
0
}
2306
2307
0
void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater) {
2308
0
  nghttp2_mem *mem;
2309
2310
0
  mem = inflater->ctx.mem;
2311
0
  nghttp2_hd_inflate_free(inflater);
2312
2313
0
  nghttp2_mem_free(mem, inflater);
2314
0
}
2315
2316
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t idx,
2317
0
                                  nghttp2_nv *nv, int indexing_mode) {
2318
0
  return emit_indname_block(bufs, idx, nv, indexing_mode);
2319
0
}
2320
2321
int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
2322
0
                                  int indexing_mode) {
2323
0
  return emit_newname_block(bufs, nv, indexing_mode);
2324
0
}
2325
2326
0
int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
2327
0
  return emit_table_size(bufs, table_size);
2328
0
}
2329
2330
nghttp2_ssize nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr,
2331
                                       int *fin, uint32_t initial, size_t shift,
2332
                                       uint8_t *in, uint8_t *last,
2333
0
                                       size_t prefix) {
2334
0
  return decode_length(res, shift_ptr, fin, initial, shift, in, last, prefix);
2335
0
}
2336
2337
static const nghttp2_nv *hd_get_table_entry(nghttp2_hd_context *context,
2338
0
                                            size_t idx) {
2339
0
  if (idx == 0) {
2340
0
    return NULL;
2341
0
  }
2342
2343
0
  --idx;
2344
2345
0
  if (!INDEX_RANGE_VALID(context, idx)) {
2346
0
    return NULL;
2347
0
  }
2348
2349
0
  return nghttp2_hd_table_get2(context, idx);
2350
0
}
2351
2352
0
size_t nghttp2_hd_deflate_get_num_table_entries(nghttp2_hd_deflater *deflater) {
2353
0
  return get_max_index(&deflater->ctx);
2354
0
}
2355
2356
const nghttp2_nv *
2357
0
nghttp2_hd_deflate_get_table_entry(nghttp2_hd_deflater *deflater, size_t idx) {
2358
0
  return hd_get_table_entry(&deflater->ctx, idx);
2359
0
}
2360
2361
size_t
2362
0
nghttp2_hd_deflate_get_dynamic_table_size(nghttp2_hd_deflater *deflater) {
2363
0
  return deflater->ctx.hd_table_bufsize;
2364
0
}
2365
2366
size_t
2367
0
nghttp2_hd_deflate_get_max_dynamic_table_size(nghttp2_hd_deflater *deflater) {
2368
0
  return deflater->ctx.hd_table_bufsize_max;
2369
0
}
2370
2371
0
size_t nghttp2_hd_inflate_get_num_table_entries(nghttp2_hd_inflater *inflater) {
2372
0
  return get_max_index(&inflater->ctx);
2373
0
}
2374
2375
const nghttp2_nv *
2376
0
nghttp2_hd_inflate_get_table_entry(nghttp2_hd_inflater *inflater, size_t idx) {
2377
0
  return hd_get_table_entry(&inflater->ctx, idx);
2378
0
}
2379
2380
size_t
2381
0
nghttp2_hd_inflate_get_dynamic_table_size(nghttp2_hd_inflater *inflater) {
2382
0
  return inflater->ctx.hd_table_bufsize;
2383
0
}
2384
2385
size_t
2386
0
nghttp2_hd_inflate_get_max_dynamic_table_size(nghttp2_hd_inflater *inflater) {
2387
0
  return inflater->ctx.hd_table_bufsize_max;
2388
0
}