Coverage Report

Created: 2026-07-16 06:32

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