Coverage Report

Created: 2025-12-03 06:25

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
    {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
127k
static int memeq(const void *s1, const void *s2, size_t n) {
114
127k
  return memcmp(s1, s2, n) == 0;
115
127k
}
116
117
/*
118
 * This function was generated by genlibtokenlookup.py.  Inspired by
119
 * h2o header lookup.  https://github.com/h2o/h2o
120
 */
121
151k
static int32_t lookup_token(const uint8_t *name, size_t namelen) {
122
151k
  switch (namelen) {
123
1.99k
  case 2:
124
1.99k
    switch (name[1]) {
125
1.35k
    case 'e':
126
1.35k
      if (memeq("t", name, 1)) {
127
819
        return NGHTTP2_TOKEN_TE;
128
819
      }
129
535
      break;
130
1.99k
    }
131
1.17k
    break;
132
3.49k
  case 3:
133
3.49k
    switch (name[2]) {
134
1.37k
    case 'a':
135
1.37k
      if (memeq("vi", name, 2)) {
136
471
        return NGHTTP2_TOKEN_VIA;
137
471
      }
138
908
      break;
139
1.27k
    case 'e':
140
1.27k
      if (memeq("ag", name, 2)) {
141
517
        return NGHTTP2_TOKEN_AGE;
142
517
      }
143
762
      break;
144
3.49k
    }
145
2.50k
    break;
146
9.50k
  case 4:
147
9.50k
    switch (name[3]) {
148
1.30k
    case 'e':
149
1.30k
      if (memeq("dat", name, 3)) {
150
428
        return NGHTTP2_TOKEN_DATE;
151
428
      }
152
877
      break;
153
1.03k
    case 'g':
154
1.03k
      if (memeq("eta", name, 3)) {
155
407
        return NGHTTP2_TOKEN_ETAG;
156
407
      }
157
631
      break;
158
1.98k
    case 'k':
159
1.98k
      if (memeq("lin", name, 3)) {
160
1.31k
        return NGHTTP2_TOKEN_LINK;
161
1.31k
      }
162
669
      break;
163
1.03k
    case 'm':
164
1.03k
      if (memeq("fro", name, 3)) {
165
420
        return NGHTTP2_TOKEN_FROM;
166
420
      }
167
617
      break;
168
1.15k
    case 't':
169
1.15k
      if (memeq("hos", name, 3)) {
170
436
        return NGHTTP2_TOKEN_HOST;
171
436
      }
172
721
      break;
173
1.20k
    case 'y':
174
1.20k
      if (memeq("var", name, 3)) {
175
435
        return NGHTTP2_TOKEN_VARY;
176
435
      }
177
767
      break;
178
9.50k
    }
179
6.06k
    break;
180
6.06k
  case 5:
181
2.76k
    switch (name[4]) {
182
790
    case 'e':
183
790
      if (memeq("rang", name, 4)) {
184
390
        return NGHTTP2_TOKEN_RANGE;
185
390
      }
186
400
      break;
187
683
    case 'h':
188
683
      if (memeq(":pat", name, 4)) {
189
368
        return NGHTTP2_TOKEN__PATH;
190
368
      }
191
315
      break;
192
591
    case 'w':
193
591
      if (memeq("allo", name, 4)) {
194
283
        return NGHTTP2_TOKEN_ALLOW;
195
283
      }
196
308
      break;
197
2.76k
    }
198
1.72k
    break;
199
2.99k
  case 6:
200
2.99k
    switch (name[5]) {
201
661
    case 'e':
202
661
      if (memeq("cooki", name, 5)) {
203
346
        return NGHTTP2_TOKEN_COOKIE;
204
346
      }
205
315
      break;
206
599
    case 'r':
207
599
      if (memeq("serve", name, 5)) {
208
279
        return NGHTTP2_TOKEN_SERVER;
209
279
      }
210
320
      break;
211
1.15k
    case 't':
212
1.15k
      if (memeq("accep", name, 5)) {
213
513
        return NGHTTP2_TOKEN_ACCEPT;
214
513
      }
215
646
      if (memeq("expec", name, 5)) {
216
302
        return NGHTTP2_TOKEN_EXPECT;
217
302
      }
218
344
      break;
219
2.99k
    }
220
1.55k
    break;
221
16.2k
  case 7:
222
16.2k
    switch (name[6]) {
223
1.29k
    case 'd':
224
1.29k
      if (memeq(":metho", name, 6)) {
225
631
        return NGHTTP2_TOKEN__METHOD;
226
631
      }
227
666
      break;
228
9.04k
    case 'e':
229
9.04k
      if (memeq(":schem", name, 6)) {
230
279
        return NGHTTP2_TOKEN__SCHEME;
231
279
      }
232
8.76k
      if (memeq("upgrad", name, 6)) {
233
7.77k
        return NGHTTP2_TOKEN_UPGRADE;
234
7.77k
      }
235
991
      break;
236
2.20k
    case 'h':
237
2.20k
      if (memeq("refres", name, 6)) {
238
1.87k
        return NGHTTP2_TOKEN_REFRESH;
239
1.87k
      }
240
330
      break;
241
742
    case 'r':
242
742
      if (memeq("refere", name, 6)) {
243
278
        return NGHTTP2_TOKEN_REFERER;
244
278
      }
245
464
      break;
246
920
    case 's':
247
920
      if (memeq(":statu", name, 6)) {
248
312
        return NGHTTP2_TOKEN__STATUS;
249
312
      }
250
608
      if (memeq("expire", name, 6)) {
251
278
        return NGHTTP2_TOKEN_EXPIRES;
252
278
      }
253
330
      break;
254
16.2k
    }
255
4.82k
    break;
256
12.1k
  case 8:
257
12.1k
    switch (name[7]) {
258
846
    case 'e':
259
846
      if (memeq("if-rang", name, 7)) {
260
293
        return NGHTTP2_TOKEN_IF_RANGE;
261
293
      }
262
553
      break;
263
590
    case 'h':
264
590
      if (memeq("if-matc", name, 7)) {
265
282
        return NGHTTP2_TOKEN_IF_MATCH;
266
282
      }
267
308
      break;
268
620
    case 'n':
269
620
      if (memeq("locatio", name, 7)) {
270
303
        return NGHTTP2_TOKEN_LOCATION;
271
303
      }
272
317
      break;
273
9.19k
    case 'y':
274
9.19k
      if (memeq("priorit", name, 7)) {
275
8.88k
        return NGHTTP2_TOKEN_PRIORITY;
276
8.88k
      }
277
315
      break;
278
12.1k
    }
279
2.39k
    break;
280
2.39k
  case 9:
281
1.81k
    switch (name[8]) {
282
1.26k
    case 'l':
283
1.26k
      if (memeq(":protoco", name, 8)) {
284
859
        return NGHTTP2_TOKEN__PROTOCOL;
285
859
      }
286
405
      break;
287
1.81k
    }
288
953
    break;
289
5.37k
  case 10:
290
5.37k
    switch (name[9]) {
291
1.92k
    case 'e':
292
1.92k
      if (memeq("keep-aliv", name, 9)) {
293
744
        return NGHTTP2_TOKEN_KEEP_ALIVE;
294
744
      }
295
1.18k
      if (memeq("set-cooki", name, 9)) {
296
279
        return NGHTTP2_TOKEN_SET_COOKIE;
297
279
      }
298
904
      break;
299
904
    case 'n':
300
736
      if (memeq("connectio", name, 9)) {
301
327
        return NGHTTP2_TOKEN_CONNECTION;
302
327
      }
303
409
      break;
304
684
    case 't':
305
684
      if (memeq("user-agen", name, 9)) {
306
309
        return NGHTTP2_TOKEN_USER_AGENT;
307
309
      }
308
375
      break;
309
966
    case 'y':
310
966
      if (memeq(":authorit", name, 9)) {
311
330
        return NGHTTP2_TOKEN__AUTHORITY;
312
330
      }
313
636
      break;
314
5.37k
    }
315
3.39k
    break;
316
3.39k
  case 11:
317
1.45k
    switch (name[10]) {
318
1.10k
    case 'r':
319
1.10k
      if (memeq("retry-afte", name, 10)) {
320
598
        return NGHTTP2_TOKEN_RETRY_AFTER;
321
598
      }
322
511
      break;
323
1.45k
    }
324
861
    break;
325
1.91k
  case 12:
326
1.91k
    switch (name[11]) {
327
684
    case 'e':
328
684
      if (memeq("content-typ", name, 11)) {
329
295
        return NGHTTP2_TOKEN_CONTENT_TYPE;
330
295
      }
331
389
      break;
332
648
    case 's':
333
648
      if (memeq("max-forward", name, 11)) {
334
284
        return NGHTTP2_TOKEN_MAX_FORWARDS;
335
284
      }
336
364
      break;
337
1.91k
    }
338
1.33k
    break;
339
4.30k
  case 13:
340
4.30k
    switch (name[12]) {
341
690
    case 'd':
342
690
      if (memeq("last-modifie", name, 12)) {
343
327
        return NGHTTP2_TOKEN_LAST_MODIFIED;
344
327
      }
345
363
      break;
346
518
    case 'e':
347
518
      if (memeq("content-rang", name, 12)) {
348
151
        return NGHTTP2_TOKEN_CONTENT_RANGE;
349
151
      }
350
367
      break;
351
644
    case 'h':
352
644
      if (memeq("if-none-matc", name, 12)) {
353
292
        return NGHTTP2_TOKEN_IF_NONE_MATCH;
354
292
      }
355
352
      break;
356
754
    case 'l':
357
754
      if (memeq("cache-contro", name, 12)) {
358
303
        return NGHTTP2_TOKEN_CACHE_CONTROL;
359
303
      }
360
451
      break;
361
624
    case 'n':
362
624
      if (memeq("authorizatio", name, 12)) {
363
278
        return NGHTTP2_TOKEN_AUTHORIZATION;
364
278
      }
365
346
      break;
366
636
    case 's':
367
636
      if (memeq("accept-range", name, 12)) {
368
282
        return NGHTTP2_TOKEN_ACCEPT_RANGES;
369
282
      }
370
354
      break;
371
4.30k
    }
372
2.67k
    break;
373
2.67k
  case 14:
374
2.04k
    switch (name[13]) {
375
861
    case 'h':
376
861
      if (memeq("content-lengt", name, 13)) {
377
278
        return NGHTTP2_TOKEN_CONTENT_LENGTH;
378
278
      }
379
583
      break;
380
762
    case 't':
381
762
      if (memeq("accept-charse", name, 13)) {
382
279
        return NGHTTP2_TOKEN_ACCEPT_CHARSET;
383
279
      }
384
483
      break;
385
2.04k
    }
386
1.48k
    break;
387
1.89k
  case 15:
388
1.89k
    switch (name[14]) {
389
885
    case 'e':
390
885
      if (memeq("accept-languag", name, 14)) {
391
395
        return NGHTTP2_TOKEN_ACCEPT_LANGUAGE;
392
395
      }
393
490
      break;
394
621
    case 'g':
395
621
      if (memeq("accept-encodin", name, 14)) {
396
280
        return NGHTTP2_TOKEN_ACCEPT_ENCODING;
397
280
      }
398
341
      break;
399
1.89k
    }
400
1.21k
    break;
401
3.83k
  case 16:
402
3.83k
    switch (name[15]) {
403
1.48k
    case 'e':
404
1.48k
      if (memeq("content-languag", name, 15)) {
405
393
        return NGHTTP2_TOKEN_CONTENT_LANGUAGE;
406
393
      }
407
1.09k
      if (memeq("www-authenticat", name, 15)) {
408
443
        return NGHTTP2_TOKEN_WWW_AUTHENTICATE;
409
443
      }
410
649
      break;
411
666
    case 'g':
412
666
      if (memeq("content-encodin", name, 15)) {
413
281
        return NGHTTP2_TOKEN_CONTENT_ENCODING;
414
281
      }
415
385
      break;
416
1.10k
    case 'n':
417
1.10k
      if (memeq("content-locatio", name, 15)) {
418
279
        return NGHTTP2_TOKEN_CONTENT_LOCATION;
419
279
      }
420
821
      if (memeq("proxy-connectio", name, 15)) {
421
392
        return NGHTTP2_TOKEN_PROXY_CONNECTION;
422
392
      }
423
429
      break;
424
3.83k
    }
425
2.04k
    break;
426
2.04k
  case 17:
427
1.93k
    switch (name[16]) {
428
651
    case 'e':
429
651
      if (memeq("if-modified-sinc", name, 16)) {
430
279
        return NGHTTP2_TOKEN_IF_MODIFIED_SINCE;
431
279
      }
432
372
      break;
433
768
    case 'g':
434
768
      if (memeq("transfer-encodin", name, 16)) {
435
421
        return NGHTTP2_TOKEN_TRANSFER_ENCODING;
436
421
      }
437
347
      break;
438
1.93k
    }
439
1.23k
    break;
440
1.64k
  case 18:
441
1.64k
    switch (name[17]) {
442
1.22k
    case 'e':
443
1.22k
      if (memeq("proxy-authenticat", name, 17)) {
444
290
        return NGHTTP2_TOKEN_PROXY_AUTHENTICATE;
445
290
      }
446
930
      break;
447
1.64k
    }
448
1.35k
    break;
449
3.00k
  case 19:
450
3.00k
    switch (name[18]) {
451
850
    case 'e':
452
850
      if (memeq("if-unmodified-sinc", name, 18)) {
453
283
        return NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE;
454
283
      }
455
567
      break;
456
980
    case 'n':
457
980
      if (memeq("content-dispositio", name, 18)) {
458
298
        return NGHTTP2_TOKEN_CONTENT_DISPOSITION;
459
298
      }
460
682
      if (memeq("proxy-authorizatio", name, 18)) {
461
281
        return NGHTTP2_TOKEN_PROXY_AUTHORIZATION;
462
281
      }
463
401
      break;
464
3.00k
    }
465
2.14k
    break;
466
2.14k
  case 25:
467
1.02k
    switch (name[24]) {
468
655
    case 'y':
469
655
      if (memeq("strict-transport-securit", name, 24)) {
470
278
        return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY;
471
278
      }
472
377
      break;
473
1.02k
    }
474
746
    break;
475
1.03k
  case 27:
476
1.03k
    switch (name[26]) {
477
638
    case 'n':
478
638
      if (memeq("access-control-allow-origi", name, 26)) {
479
284
        return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
480
284
      }
481
354
      break;
482
1.03k
    }
483
754
    break;
484
151k
  }
485
111k
  return -1;
486
151k
}
487
488
60.3k
void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv) {
489
60.3k
  ent->nv = *nv;
490
60.3k
  ent->cnv.name = nv->name->base;
491
60.3k
  ent->cnv.namelen = nv->name->len;
492
60.3k
  ent->cnv.value = nv->value->base;
493
60.3k
  ent->cnv.valuelen = nv->value->len;
494
60.3k
  ent->cnv.flags = nv->flags;
495
60.3k
  ent->next = NULL;
496
60.3k
  ent->hash = 0;
497
498
60.3k
  nghttp2_rcbuf_incref(ent->nv.name);
499
60.3k
  nghttp2_rcbuf_incref(ent->nv.value);
500
60.3k
}
501
502
60.3k
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) {
503
60.3k
  nghttp2_rcbuf_decref(ent->nv.value);
504
60.3k
  nghttp2_rcbuf_decref(ent->nv.name);
505
60.3k
}
506
507
24.3k
static int name_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
508
24.3k
  return a->name->len == b->namelen &&
509
24.3k
         memeq(a->name->base, b->name, b->namelen);
510
24.3k
}
511
512
24.7k
static int value_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
513
24.7k
  return a->value->len == b->valuelen &&
514
23.9k
         memeq(a->value->base, b->value, b->valuelen);
515
24.7k
}
516
517
31.5k
static uint32_t name_hash(const nghttp2_nv *nv) {
518
  /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */
519
31.5k
  uint32_t h = 2166136261u;
520
31.5k
  size_t i;
521
522
85.9k
  for (i = 0; i < nv->namelen; ++i) {
523
54.3k
    h ^= nv->name[i];
524
54.3k
    h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
525
54.3k
  }
526
527
31.5k
  return h;
528
31.5k
}
529
530
27.9k
static void hd_map_init(nghttp2_hd_map *map) {
531
27.9k
  memset(map, 0, sizeof(nghttp2_hd_map));
532
27.9k
}
533
534
8.87k
static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
535
8.87k
  nghttp2_hd_entry **bucket;
536
537
8.87k
  bucket = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
538
539
8.87k
  if (*bucket == NULL) {
540
7.97k
    *bucket = ent;
541
7.97k
    return;
542
7.97k
  }
543
544
  /* lower index is linked near the root */
545
898
  ent->next = *bucket;
546
898
  *bucket = ent;
547
898
}
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
33.1k
                                     uint32_t hash, int name_only) {
552
33.1k
  nghttp2_hd_entry *p;
553
33.1k
  nghttp2_hd_entry *res = NULL;
554
555
33.1k
  *exact_match = 0;
556
557
35.1k
  for (p = map->table[hash & (HD_MAP_SIZE - 1)]; p; p = p->next) {
558
25.2k
    if (token != p->nv.token ||
559
25.1k
        (token == -1 && (hash != p->hash || !name_eq(&p->nv, nv)))) {
560
485
      continue;
561
485
    }
562
24.7k
    if (!res) {
563
23.8k
      res = p;
564
23.8k
      if (name_only) {
565
18
        break;
566
18
      }
567
23.8k
    }
568
24.7k
    if (value_eq(&p->nv, nv)) {
569
23.1k
      res = p;
570
23.1k
      *exact_match = 1;
571
23.1k
      break;
572
23.1k
    }
573
24.7k
  }
574
575
33.1k
  return res;
576
33.1k
}
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
55.8k
                           nghttp2_mem *mem) {
596
55.8k
  size_t size;
597
55.8k
  const size_t max_size = SIZE_MAX / sizeof(nghttp2_hd_entry *);
598
599
55.8k
  if (bufsize > max_size) {
600
0
    return NGHTTP2_ERR_NOMEM;
601
0
  }
602
603
446k
  for (size = 1; size < bufsize; size <<= 1)
604
390k
    ;
605
606
55.8k
  if (size > max_size) {
607
0
    return NGHTTP2_ERR_NOMEM;
608
0
  }
609
610
55.8k
  ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
611
55.8k
  if (ringbuf->buffer == NULL) {
612
0
    return NGHTTP2_ERR_NOMEM;
613
0
  }
614
55.8k
  ringbuf->mask = size - 1;
615
55.8k
  ringbuf->first = 0;
616
55.8k
  ringbuf->len = 0;
617
55.8k
  return 0;
618
55.8k
}
619
620
static nghttp2_hd_entry *hd_ringbuf_get(nghttp2_hd_ringbuf *ringbuf,
621
136k
                                        size_t idx) {
622
136k
  assert(idx < ringbuf->len);
623
136k
  return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask];
624
136k
}
625
626
static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
627
60.3k
                              nghttp2_mem *mem) {
628
60.3k
  size_t i;
629
60.3k
  size_t size;
630
60.3k
  nghttp2_hd_entry **buffer;
631
632
60.3k
  if (ringbuf->mask + 1 >= bufsize) {
633
60.3k
    return 0;
634
60.3k
  }
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
55.8k
static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
652
55.8k
  size_t i;
653
55.8k
  if (ringbuf == NULL) {
654
0
    return;
655
0
  }
656
104k
  for (i = 0; i < ringbuf->len; ++i) {
657
49.0k
    nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
658
659
49.0k
    nghttp2_hd_entry_free(ent);
660
49.0k
    nghttp2_mem_free(mem, ent);
661
49.0k
  }
662
55.8k
  nghttp2_mem_free(mem, ringbuf->buffer);
663
55.8k
}
664
665
static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf,
666
60.3k
                                 nghttp2_hd_entry *ent, nghttp2_mem *mem) {
667
60.3k
  int rv;
668
669
60.3k
  rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem);
670
671
60.3k
  if (rv != 0) {
672
0
    return rv;
673
0
  }
674
675
60.3k
  ringbuf->buffer[--ringbuf->first & ringbuf->mask] = ent;
676
60.3k
  ++ringbuf->len;
677
678
60.3k
  return 0;
679
60.3k
}
680
681
11.2k
static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) {
682
11.2k
  assert(ringbuf->len > 0);
683
11.2k
  --ringbuf->len;
684
11.2k
}
685
686
55.8k
static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
687
55.8k
  int rv;
688
55.8k
  context->mem = mem;
689
55.8k
  context->bad = 0;
690
55.8k
  context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
691
55.8k
  rv = hd_ringbuf_init(
692
55.8k
    &context->hd_table,
693
55.8k
    context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
694
55.8k
  if (rv != 0) {
695
0
    return rv;
696
0
  }
697
698
55.8k
  context->hd_table_bufsize = 0;
699
55.8k
  context->next_seq = 0;
700
701
55.8k
  return 0;
702
55.8k
}
703
704
55.8k
static void hd_context_free(nghttp2_hd_context *context) {
705
55.8k
  hd_ringbuf_free(&context->hd_table, context->mem);
706
55.8k
}
707
708
4.73k
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) {
709
4.73k
  return nghttp2_hd_deflate_init2(
710
4.73k
    deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem);
711
4.73k
}
712
713
int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
714
                             size_t max_deflate_dynamic_table_size,
715
27.9k
                             nghttp2_mem *mem) {
716
27.9k
  int rv;
717
27.9k
  rv = hd_context_init(&deflater->ctx, mem);
718
27.9k
  if (rv != 0) {
719
0
    return rv;
720
0
  }
721
722
27.9k
  hd_map_init(&deflater->map);
723
724
27.9k
  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
27.9k
  } else {
728
27.9k
    deflater->notify_table_size_change = 0;
729
27.9k
  }
730
731
27.9k
  deflater->deflate_hd_table_bufsize_max = max_deflate_dynamic_table_size;
732
27.9k
  deflater->min_hd_table_bufsize_max = UINT32_MAX;
733
734
27.9k
  return 0;
735
27.9k
}
736
737
27.9k
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
738
27.9k
  int rv;
739
740
27.9k
  rv = hd_context_init(&inflater->ctx, mem);
741
27.9k
  if (rv != 0) {
742
0
    goto fail;
743
0
  }
744
745
27.9k
  inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
746
27.9k
  inflater->min_hd_table_bufsize_max = UINT32_MAX;
747
748
27.9k
  inflater->nv_name_keep = NULL;
749
27.9k
  inflater->nv_value_keep = NULL;
750
751
27.9k
  inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
752
27.9k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
753
754
27.9k
  nghttp2_buf_init(&inflater->namebuf);
755
27.9k
  nghttp2_buf_init(&inflater->valuebuf);
756
757
27.9k
  inflater->namercbuf = NULL;
758
27.9k
  inflater->valuercbuf = NULL;
759
760
27.9k
  inflater->huffman_encoded = 0;
761
27.9k
  inflater->index = 0;
762
27.9k
  inflater->left = 0;
763
27.9k
  inflater->shift = 0;
764
27.9k
  inflater->index_required = 0;
765
27.9k
  inflater->no_index = 0;
766
767
27.9k
  return 0;
768
769
0
fail:
770
0
  return rv;
771
27.9k
}
772
773
430k
static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
774
430k
  nghttp2_rcbuf_decref(inflater->nv_value_keep);
775
430k
  nghttp2_rcbuf_decref(inflater->nv_name_keep);
776
777
430k
  inflater->nv_value_keep = NULL;
778
430k
  inflater->nv_name_keep = NULL;
779
430k
}
780
781
27.9k
void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
782
27.9k
  hd_context_free(&deflater->ctx);
783
27.9k
}
784
785
27.9k
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
786
27.9k
  hd_inflate_keep_free(inflater);
787
788
27.9k
  nghttp2_rcbuf_decref(inflater->valuercbuf);
789
27.9k
  nghttp2_rcbuf_decref(inflater->namercbuf);
790
791
27.9k
  hd_context_free(&inflater->ctx);
792
27.9k
}
793
794
105k
static size_t entry_room(size_t namelen, size_t valuelen) {
795
105k
  return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
796
105k
}
797
798
329k
static void emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
799
329k
  DEBUGF("inflatehd: header emission: %s: %s\n", nv->name->base,
800
329k
         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
329k
  *nv_out = *nv;
804
329k
}
805
806
42.1k
static size_t count_encoded_length(size_t n, size_t prefix) {
807
42.1k
  size_t k = (size_t)((1 << prefix) - 1);
808
42.1k
  size_t len = 0;
809
810
42.1k
  if (n < k) {
811
41.3k
    return 1;
812
41.3k
  }
813
814
798
  n -= k;
815
798
  ++len;
816
817
1.27k
  for (; n >= 128; n >>= 7, ++len)
818
481
    ;
819
820
798
  return len + 1;
821
42.1k
}
822
823
42.1k
static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
824
42.1k
  size_t k = (size_t)((1 << prefix) - 1);
825
42.1k
  uint8_t *begin = buf;
826
827
42.1k
  *buf = (uint8_t)(*buf & ~k);
828
829
42.1k
  if (n < k) {
830
41.3k
    *buf = (uint8_t)(*buf | n);
831
41.3k
    return 1;
832
41.3k
  }
833
834
798
  *buf = (uint8_t)(*buf | k);
835
798
  ++buf;
836
837
798
  n -= k;
838
839
1.27k
  for (; n >= 128; n >>= 7) {
840
481
    *buf++ = (uint8_t)((1 << 7) | (n & 0x7f));
841
481
  }
842
843
798
  *buf++ = (uint8_t)n;
844
845
798
  return (size_t)(buf - begin);
846
42.1k
}
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
505k
                                   size_t prefix) {
869
505k
  uint32_t k = (uint8_t)((1 << prefix) - 1);
870
505k
  uint32_t n = initial;
871
505k
  const uint8_t *start = in;
872
873
505k
  *shift_ptr = 0;
874
505k
  *fin = 0;
875
876
505k
  if (n == 0) {
877
503k
    if ((*in & k) != k) {
878
492k
      *res = (*in) & k;
879
492k
      *fin = 1;
880
492k
      return 1;
881
492k
    }
882
883
11.0k
    n = k;
884
885
11.0k
    if (++in == last) {
886
236
      *res = n;
887
236
      return (nghttp2_ssize)(in - start);
888
236
    }
889
11.0k
  }
890
891
32.7k
  for (; in != last; ++in, shift += 7) {
892
30.3k
    uint32_t add = *in & 0x7f;
893
894
30.3k
    if (shift >= 32) {
895
51
      DEBUGF("inflate: shift exponent overflow\n");
896
51
      return -1;
897
51
    }
898
899
30.2k
    if ((UINT32_MAX >> shift) < add) {
900
76
      DEBUGF("inflate: integer overflow on shift\n");
901
76
      return -1;
902
76
    }
903
904
30.1k
    add <<= shift;
905
906
30.1k
    if (UINT32_MAX - add < n) {
907
89
      DEBUGF("inflate: integer overflow on addition\n");
908
89
      return -1;
909
89
    }
910
911
30.1k
    n += add;
912
913
30.1k
    if ((*in & (1 << 7)) == 0) {
914
9.80k
      break;
915
9.80k
    }
916
30.1k
  }
917
918
12.2k
  *shift_ptr = shift;
919
920
12.2k
  if (in == last) {
921
2.40k
    *res = n;
922
2.40k
    return (nghttp2_ssize)(in - start);
923
2.40k
  }
924
925
9.80k
  *res = n;
926
9.80k
  *fin = 1;
927
9.80k
  return (nghttp2_ssize)(in + 1 - start);
928
12.2k
}
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
24.1k
static int emit_indexed_block(nghttp2_bufs *bufs, size_t idx) {
959
24.1k
  int rv;
960
24.1k
  size_t blocklen;
961
24.1k
  uint8_t sb[16];
962
24.1k
  uint8_t *bufp;
963
964
24.1k
  blocklen = count_encoded_length(idx + 1, 7);
965
966
24.1k
  DEBUGF("deflatehd: emit indexed index=%zu, %zu bytes\n", idx, blocklen);
967
968
24.1k
  if (sizeof(sb) < blocklen) {
969
0
    return NGHTTP2_ERR_HEADER_COMP;
970
0
  }
971
972
24.1k
  bufp = sb;
973
24.1k
  *bufp = 0x80u;
974
24.1k
  encode_length(bufp, idx + 1, 7);
975
976
24.1k
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
977
24.1k
  if (rv != 0) {
978
0
    return rv;
979
0
  }
980
981
24.1k
  return 0;
982
24.1k
}
983
984
17.0k
static int emit_string(nghttp2_bufs *bufs, const uint8_t *str, size_t len) {
985
17.0k
  int rv;
986
17.0k
  uint8_t sb[16];
987
17.0k
  uint8_t *bufp;
988
17.0k
  size_t blocklen;
989
17.0k
  size_t enclen;
990
17.0k
  int huffman = 0;
991
992
17.0k
  enclen = nghttp2_hd_huff_encode_count(str, len);
993
994
17.0k
  if (enclen < len) {
995
1.30k
    huffman = 1;
996
15.7k
  } else {
997
15.7k
    enclen = len;
998
15.7k
  }
999
1000
17.0k
  blocklen = count_encoded_length(enclen, 7);
1001
1002
17.0k
  DEBUGF("deflatehd: emit string str=%.*s, length=%zu, huffman=%d, "
1003
17.0k
         "encoded_length=%zu\n",
1004
17.0k
         (int)len, (const char *)str, len, huffman, enclen);
1005
1006
17.0k
  if (sizeof(sb) < blocklen) {
1007
0
    return NGHTTP2_ERR_HEADER_COMP;
1008
0
  }
1009
1010
17.0k
  bufp = sb;
1011
17.0k
  *bufp = huffman ? 1 << 7 : 0;
1012
17.0k
  encode_length(bufp, enclen, 7);
1013
1014
17.0k
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
1015
17.0k
  if (rv != 0) {
1016
0
    return rv;
1017
0
  }
1018
1019
17.0k
  if (huffman) {
1020
1.30k
    rv = nghttp2_hd_huff_encode(bufs, str, len);
1021
15.7k
  } else {
1022
15.7k
    assert(enclen == len);
1023
15.7k
    rv = nghttp2_bufs_add(bufs, str, len);
1024
15.7k
  }
1025
1026
17.0k
  return rv;
1027
17.0k
}
1028
1029
8.99k
static uint8_t pack_first_byte(int indexing_mode) {
1030
8.99k
  switch (indexing_mode) {
1031
8.87k
  case NGHTTP2_HD_WITH_INDEXING:
1032
8.87k
    return 0x40u;
1033
63
  case NGHTTP2_HD_WITHOUT_INDEXING:
1034
63
    return 0;
1035
63
  case NGHTTP2_HD_NEVER_INDEXING:
1036
63
    return 0x10u;
1037
0
  default:
1038
0
    assert(0);
1039
8.99k
  }
1040
  /* This is required to compile with android NDK r10d +
1041
     --enable-werror */
1042
0
  return 0;
1043
8.99k
}
1044
1045
static int emit_indname_block(nghttp2_bufs *bufs, size_t idx,
1046
921
                              const nghttp2_nv *nv, int indexing_mode) {
1047
921
  int rv;
1048
921
  uint8_t *bufp;
1049
921
  size_t blocklen;
1050
921
  uint8_t sb[16];
1051
921
  size_t prefixlen;
1052
1053
921
  if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1054
795
    prefixlen = 6;
1055
795
  } else {
1056
126
    prefixlen = 4;
1057
126
  }
1058
1059
921
  DEBUGF("deflatehd: emit indname index=%zu, valuelen=%zu, indexing_mode=%d\n",
1060
921
         idx, nv->valuelen, indexing_mode);
1061
1062
921
  blocklen = count_encoded_length(idx + 1, prefixlen);
1063
1064
921
  if (sizeof(sb) < blocklen) {
1065
0
    return NGHTTP2_ERR_HEADER_COMP;
1066
0
  }
1067
1068
921
  bufp = sb;
1069
1070
921
  *bufp = pack_first_byte(indexing_mode);
1071
1072
921
  encode_length(bufp, idx + 1, prefixlen);
1073
1074
921
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
1075
921
  if (rv != 0) {
1076
0
    return rv;
1077
0
  }
1078
1079
921
  rv = emit_string(bufs, nv->value, nv->valuelen);
1080
921
  if (rv != 0) {
1081
0
    return rv;
1082
0
  }
1083
1084
921
  return 0;
1085
921
}
1086
1087
static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
1088
8.07k
                              int indexing_mode) {
1089
8.07k
  int rv;
1090
1091
8.07k
  DEBUGF(
1092
8.07k
    "deflatehd: emit newname namelen=%zu, valuelen=%zu, indexing_mode=%d\n",
1093
8.07k
    nv->namelen, nv->valuelen, indexing_mode);
1094
1095
8.07k
  rv = nghttp2_bufs_addb(bufs, pack_first_byte(indexing_mode));
1096
8.07k
  if (rv != 0) {
1097
0
    return rv;
1098
0
  }
1099
1100
8.07k
  rv = emit_string(bufs, nv->name, nv->namelen);
1101
8.07k
  if (rv != 0) {
1102
0
    return rv;
1103
0
  }
1104
1105
8.07k
  rv = emit_string(bufs, nv->value, nv->valuelen);
1106
8.07k
  if (rv != 0) {
1107
0
    return rv;
1108
0
  }
1109
1110
8.07k
  return 0;
1111
8.07k
}
1112
1113
static int add_hd_table_incremental(nghttp2_hd_context *context,
1114
                                    nghttp2_hd_nv *nv, nghttp2_hd_map *map,
1115
61.7k
                                    uint32_t hash) {
1116
61.7k
  int rv;
1117
61.7k
  nghttp2_hd_entry *new_ent;
1118
61.7k
  size_t room;
1119
61.7k
  nghttp2_mem *mem;
1120
1121
61.7k
  mem = context->mem;
1122
61.7k
  room = entry_room(nv->name->len, nv->value->len);
1123
1124
72.0k
  while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
1125
11.7k
         context->hd_table.len > 0) {
1126
10.3k
    size_t idx = context->hd_table.len - 1;
1127
10.3k
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1128
1129
10.3k
    context->hd_table_bufsize -=
1130
10.3k
      entry_room(ent->nv.name->len, ent->nv.value->len);
1131
1132
10.3k
    DEBUGF("hpack: remove item from header table: %s: %s\n",
1133
10.3k
           (char *)ent->nv.name->base, (char *)ent->nv.value->base);
1134
1135
10.3k
    hd_ringbuf_pop_back(&context->hd_table);
1136
10.3k
    if (map) {
1137
0
      hd_map_remove(map, ent);
1138
0
    }
1139
1140
10.3k
    nghttp2_hd_entry_free(ent);
1141
10.3k
    nghttp2_mem_free(mem, ent);
1142
10.3k
  }
1143
1144
61.7k
  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
1.41k
    return 0;
1148
1.41k
  }
1149
1150
60.3k
  new_ent = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry));
1151
60.3k
  if (new_ent == NULL) {
1152
0
    return NGHTTP2_ERR_NOMEM;
1153
0
  }
1154
1155
60.3k
  nghttp2_hd_entry_init(new_ent, nv);
1156
1157
60.3k
  rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
1158
1159
60.3k
  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
60.3k
  new_ent->seq = context->next_seq++;
1167
60.3k
  new_ent->hash = hash;
1168
1169
60.3k
  if (map) {
1170
8.87k
    hd_map_insert(map, new_ent);
1171
8.87k
  }
1172
1173
60.3k
  context->hd_table_bufsize += room;
1174
1175
60.3k
  return 0;
1176
60.3k
}
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
1.26k
                                         int name_only) {
1186
1.26k
  search_result res = {token, 0};
1187
1.26k
  int i;
1188
1.26k
  const nghttp2_hd_static_entry *ent;
1189
1190
1.26k
  if (name_only) {
1191
63
    return res;
1192
63
  }
1193
1194
1.20k
  for (i = token;
1195
1.72k
       i <= NGHTTP2_TOKEN_WWW_AUTHENTICATE && static_table[i].token == token;
1196
1.48k
       ++i) {
1197
1.48k
    ent = &static_table[i];
1198
1.48k
    if (ent->value.len == nv->valuelen &&
1199
1.13k
        memcmp(ent->value.base, nv->value, nv->valuelen) == 0) {
1200
958
      res.index = i;
1201
958
      res.name_value_match = 1;
1202
958
      return res;
1203
958
    }
1204
1.48k
  }
1205
243
  return res;
1206
1.20k
}
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
33.1k
                                     uint32_t hash) {
1212
33.1k
  search_result res = {-1, 0};
1213
33.1k
  const nghttp2_hd_entry *ent;
1214
33.1k
  int exact_match;
1215
33.1k
  int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING;
1216
1217
33.1k
  exact_match = 0;
1218
33.1k
  ent = hd_map_find(map, &exact_match, nv, token, hash, name_only);
1219
1220
33.1k
  if (!exact_match && token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1221
1.26k
    return search_static_table(nv, token, name_only);
1222
1.26k
  }
1223
1224
31.8k
  if (ent == NULL) {
1225
8.07k
    return res;
1226
8.07k
  }
1227
1228
23.7k
  res.index = (nghttp2_ssize)(context->next_seq - 1 - ent->seq +
1229
23.7k
                              NGHTTP2_STATIC_TABLE_LENGTH);
1230
23.7k
  res.name_value_match = exact_match;
1231
1232
23.7k
  return res;
1233
31.8k
}
1234
1235
static void hd_context_shrink_table_size(nghttp2_hd_context *context,
1236
7.29k
                                         nghttp2_hd_map *map) {
1237
7.29k
  nghttp2_mem *mem;
1238
1239
7.29k
  mem = context->mem;
1240
1241
8.20k
  while (context->hd_table_bufsize > context->hd_table_bufsize_max &&
1242
911
         context->hd_table.len > 0) {
1243
911
    size_t idx = context->hd_table.len - 1;
1244
911
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1245
911
    context->hd_table_bufsize -=
1246
911
      entry_room(ent->nv.name->len, ent->nv.value->len);
1247
911
    hd_ringbuf_pop_back(&context->hd_table);
1248
911
    if (map) {
1249
0
      hd_map_remove(map, ent);
1250
0
    }
1251
1252
911
    nghttp2_hd_entry_free(ent);
1253
911
    nghttp2_mem_free(mem, ent);
1254
911
  }
1255
7.29k
}
1256
1257
int nghttp2_hd_deflate_change_table_size(
1258
2.65k
  nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
1259
2.65k
  size_t next_bufsize = nghttp2_min_size(
1260
2.65k
    settings_max_dynamic_table_size, deflater->deflate_hd_table_bufsize_max);
1261
1262
2.65k
  deflater->ctx.hd_table_bufsize_max = next_bufsize;
1263
1264
2.65k
  deflater->min_hd_table_bufsize_max =
1265
2.65k
    nghttp2_min_size(deflater->min_hd_table_bufsize_max, next_bufsize);
1266
1267
2.65k
  deflater->notify_table_size_change = 1;
1268
1269
2.65k
  hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
1270
2.65k
  return 0;
1271
2.65k
}
1272
1273
int nghttp2_hd_inflate_change_table_size(
1274
121
  nghttp2_hd_inflater *inflater, size_t settings_max_dynamic_table_size) {
1275
121
  switch (inflater->state) {
1276
22
  case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1277
121
  case NGHTTP2_HD_STATE_INFLATE_START:
1278
121
    break;
1279
0
  default:
1280
0
    return NGHTTP2_ERR_INVALID_STATE;
1281
121
  }
1282
1283
121
  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
121
  if (inflater->ctx.hd_table_bufsize_max > settings_max_dynamic_table_size) {
1293
95
    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
95
    inflater->min_hd_table_bufsize_max = settings_max_dynamic_table_size;
1297
1298
95
    inflater->ctx.hd_table_bufsize_max = settings_max_dynamic_table_size;
1299
1300
95
    hd_context_shrink_table_size(&inflater->ctx, NULL);
1301
95
  }
1302
1303
121
  return 0;
1304
121
}
1305
1306
#define INDEX_RANGE_VALID(context, idx)                                        \
1307
0
  ((idx) < (context)->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH)
1308
1309
212k
static size_t get_max_index(nghttp2_hd_context *context) {
1310
212k
  return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH;
1311
212k
}
1312
1313
211k
nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
1314
211k
  assert(INDEX_RANGE_VALID(context, idx));
1315
211k
  if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1316
75.8k
    return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
1317
75.8k
      ->nv;
1318
135k
  } else {
1319
135k
    const nghttp2_hd_static_entry *ent = &static_table[idx];
1320
135k
    nghttp2_hd_nv nv = {(nghttp2_rcbuf *)&ent->name,
1321
135k
                        (nghttp2_rcbuf *)&ent->value, ent->token,
1322
135k
                        NGHTTP2_NV_FLAG_NONE};
1323
135k
    return nv;
1324
135k
  }
1325
211k
}
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
33.0k
                                      const nghttp2_nv *nv, int32_t token) {
1341
33.0k
  if (token == NGHTTP2_TOKEN__PATH || token == NGHTTP2_TOKEN_AGE ||
1342
32.8k
      token == NGHTTP2_TOKEN_CONTENT_LENGTH || token == NGHTTP2_TOKEN_ETAG ||
1343
32.8k
      token == NGHTTP2_TOKEN_IF_MODIFIED_SINCE ||
1344
32.8k
      token == NGHTTP2_TOKEN_IF_NONE_MATCH || token == NGHTTP2_TOKEN_LOCATION ||
1345
32.7k
      token == NGHTTP2_TOKEN_SET_COOKIE ||
1346
32.7k
      entry_room(nv->namelen, nv->valuelen) >
1347
32.7k
        deflater->ctx.hd_table_bufsize_max * 3 / 4) {
1348
286
    return NGHTTP2_HD_WITHOUT_INDEXING;
1349
286
  }
1350
1351
32.7k
  return NGHTTP2_HD_WITH_INDEXING;
1352
33.0k
}
1353
1354
static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
1355
33.1k
                      const nghttp2_nv *nv) {
1356
33.1k
  int rv;
1357
33.1k
  search_result res;
1358
33.1k
  nghttp2_ssize idx;
1359
33.1k
  int indexing_mode;
1360
33.1k
  int32_t token;
1361
33.1k
  nghttp2_mem *mem;
1362
33.1k
  uint32_t hash = 0;
1363
1364
33.1k
  DEBUGF("deflatehd: deflating %.*s: %.*s\n", (int)nv->namelen, nv->name,
1365
33.1k
         (int)nv->valuelen, nv->value);
1366
1367
33.1k
  mem = deflater->ctx.mem;
1368
1369
33.1k
  token = lookup_token(nv->name, nv->namelen);
1370
33.1k
  if (token == -1) {
1371
31.5k
    hash = name_hash(nv);
1372
31.5k
  } else if (token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1373
1.31k
    hash = static_table[token].hash;
1374
1.31k
  }
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
33.1k
  indexing_mode = token == NGHTTP2_TOKEN_AUTHORIZATION ||
1381
33.0k
                      (token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) ||
1382
33.0k
                      (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX)
1383
33.1k
                    ? NGHTTP2_HD_NEVER_INDEXING
1384
33.1k
                    : hd_deflate_decide_indexing(deflater, nv, token);
1385
1386
33.1k
  res = search_hd_table(&deflater->ctx, nv, token, indexing_mode,
1387
33.1k
                        &deflater->map, hash);
1388
1389
33.1k
  idx = res.index;
1390
1391
33.1k
  if (res.name_value_match) {
1392
24.1k
    DEBUGF("deflatehd: name/value match index=%td\n", idx);
1393
1394
24.1k
    rv = emit_indexed_block(bufs, (size_t)idx);
1395
24.1k
    if (rv != 0) {
1396
0
      return rv;
1397
0
    }
1398
1399
24.1k
    return 0;
1400
24.1k
  }
1401
1402
8.99k
  if (res.index != -1) {
1403
921
    DEBUGF("deflatehd: name match index=%td\n", res.index);
1404
921
  }
1405
1406
8.99k
  if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1407
8.87k
    nghttp2_hd_nv hd_nv;
1408
1409
8.87k
    if (idx != -1) {
1410
795
      hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name;
1411
795
      nghttp2_rcbuf_incref(hd_nv.name);
1412
8.07k
    } else {
1413
8.07k
      rv = nghttp2_rcbuf_new2(&hd_nv.name, nv->name, nv->namelen, mem);
1414
8.07k
      if (rv != 0) {
1415
0
        return rv;
1416
0
      }
1417
8.07k
    }
1418
1419
8.87k
    rv = nghttp2_rcbuf_new2(&hd_nv.value, nv->value, nv->valuelen, mem);
1420
1421
8.87k
    if (rv != 0) {
1422
0
      nghttp2_rcbuf_decref(hd_nv.name);
1423
0
      return rv;
1424
0
    }
1425
1426
8.87k
    hd_nv.token = token;
1427
8.87k
    hd_nv.flags = NGHTTP2_NV_FLAG_NONE;
1428
1429
8.87k
    rv = add_hd_table_incremental(&deflater->ctx, &hd_nv, &deflater->map, hash);
1430
1431
8.87k
    nghttp2_rcbuf_decref(hd_nv.value);
1432
8.87k
    nghttp2_rcbuf_decref(hd_nv.name);
1433
1434
8.87k
    if (rv != 0) {
1435
0
      return NGHTTP2_ERR_HEADER_COMP;
1436
0
    }
1437
8.87k
  }
1438
8.99k
  if (idx == -1) {
1439
8.07k
    rv = emit_newname_block(bufs, nv, indexing_mode);
1440
8.07k
  } else {
1441
921
    rv = emit_indname_block(bufs, (size_t)idx, nv, indexing_mode);
1442
921
  }
1443
8.99k
  if (rv != 0) {
1444
0
    return rv;
1445
0
  }
1446
1447
8.99k
  return 0;
1448
8.99k
}
1449
1450
int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
1451
                               nghttp2_bufs *bufs, const nghttp2_nv *nv,
1452
4.73k
                               size_t nvlen) {
1453
4.73k
  size_t i;
1454
4.73k
  int rv = 0;
1455
1456
4.73k
  if (deflater->ctx.bad) {
1457
0
    return NGHTTP2_ERR_HEADER_COMP;
1458
0
  }
1459
1460
4.73k
  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
37.8k
  for (i = 0; i < nvlen; ++i) {
1484
33.1k
    rv = deflate_nv(deflater, bufs, &nv[i]);
1485
33.1k
    if (rv != 0) {
1486
0
      goto fail;
1487
0
    }
1488
33.1k
  }
1489
1490
4.73k
  DEBUGF("deflatehd: all input name/value pairs were deflated\n");
1491
1492
4.73k
  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
4.73k
}
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
286k
                                           const uint8_t *in) {
1651
286k
  inflater->huffman_encoded = (*in & (1 << 7)) != 0;
1652
286k
}
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
505k
                                         size_t maxlen) {
1671
505k
  nghttp2_ssize rv;
1672
505k
  uint32_t out;
1673
1674
505k
  *rfin = 0;
1675
1676
505k
  rv = decode_length(&out, &inflater->shift, rfin, (uint32_t)inflater->left,
1677
505k
                     inflater->shift, in, last, prefix);
1678
1679
505k
  if (rv == -1) {
1680
216
    DEBUGF("inflatehd: integer decoding failed\n");
1681
216
    return NGHTTP2_ERR_HEADER_COMP;
1682
216
  }
1683
1684
505k
  if (out > maxlen) {
1685
1.52k
    DEBUGF("inflatehd: integer exceeded the maximum value %zu\n", maxlen);
1686
1.52k
    return NGHTTP2_ERR_HEADER_COMP;
1687
1.52k
  }
1688
1689
503k
  inflater->left = out;
1690
1691
503k
  DEBUGF("inflatehd: decoded integer is %u\n", out);
1692
1693
503k
  return rv;
1694
505k
}
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
37.7k
                                          const uint8_t *last) {
1712
37.7k
  nghttp2_ssize readlen;
1713
37.7k
  int fin = 0;
1714
37.7k
  if ((size_t)(last - in) >= inflater->left) {
1715
37.5k
    last = in + inflater->left;
1716
37.5k
    fin = 1;
1717
37.5k
  }
1718
37.7k
  readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
1719
37.7k
                                   (size_t)(last - in), fin);
1720
1721
37.7k
  if (readlen < 0) {
1722
29
    DEBUGF("inflatehd: huffman decoding failed\n");
1723
29
    return readlen;
1724
29
  }
1725
37.7k
  if (nghttp2_hd_huff_decode_failure_state(&inflater->huff_decode_ctx)) {
1726
17
    DEBUGF("inflatehd: huffman decoding failed\n");
1727
17
    return NGHTTP2_ERR_HEADER_COMP;
1728
17
  }
1729
1730
37.7k
  inflater->left -= (size_t)readlen;
1731
37.7k
  return readlen;
1732
37.7k
}
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
247k
                                     const uint8_t *last) {
1749
247k
  size_t len = nghttp2_min_size((size_t)(last - in), inflater->left);
1750
1751
247k
  buf->last = nghttp2_cpymem(buf->last, in, len);
1752
1753
247k
  inflater->left -= len;
1754
247k
  return (nghttp2_ssize)len;
1755
247k
}
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
162k
                                      nghttp2_hd_nv *nv_out) {
1763
162k
  nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1764
1765
162k
  emit_header(nv_out, &nv);
1766
162k
}
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
118k
                                     nghttp2_hd_nv *nv_out) {
1781
118k
  nghttp2_hd_nv nv;
1782
118k
  int rv;
1783
1784
118k
  if (inflater->no_index) {
1785
4.59k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1786
113k
  } else {
1787
113k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1788
113k
  }
1789
1790
118k
  nv.name = inflater->namercbuf;
1791
118k
  nv.value = inflater->valuercbuf;
1792
118k
  nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len);
1793
1794
118k
  if (inflater->index_required) {
1795
23.2k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1796
1797
23.2k
    if (rv != 0) {
1798
0
      return rv;
1799
0
    }
1800
23.2k
  }
1801
1802
118k
  emit_header(nv_out, &nv);
1803
1804
118k
  inflater->nv_name_keep = nv.name;
1805
118k
  inflater->nv_value_keep = nv.value;
1806
1807
118k
  inflater->namercbuf = NULL;
1808
118k
  inflater->valuercbuf = NULL;
1809
1810
118k
  return 0;
1811
118k
}
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
47.8k
                                     nghttp2_hd_nv *nv_out) {
1826
47.8k
  nghttp2_hd_nv nv;
1827
47.8k
  int rv;
1828
1829
47.8k
  nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1830
1831
47.8k
  if (inflater->no_index) {
1832
3.96k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1833
43.9k
  } else {
1834
43.9k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1835
43.9k
  }
1836
1837
47.8k
  nghttp2_rcbuf_incref(nv.name);
1838
1839
47.8k
  nv.value = inflater->valuercbuf;
1840
1841
47.8k
  if (inflater->index_required) {
1842
29.6k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1843
29.6k
    if (rv != 0) {
1844
0
      nghttp2_rcbuf_decref(nv.name);
1845
0
      return NGHTTP2_ERR_NOMEM;
1846
0
    }
1847
29.6k
  }
1848
1849
47.8k
  emit_header(nv_out, &nv);
1850
1851
47.8k
  inflater->nv_name_keep = nv.name;
1852
47.8k
  inflater->nv_value_keep = nv.value;
1853
1854
47.8k
  inflater->valuercbuf = NULL;
1855
1856
47.8k
  return 0;
1857
47.8k
}
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
18.9k
                                     int in_final) {
1877
18.9k
  nghttp2_ssize rv;
1878
18.9k
  nghttp2_hd_nv hd_nv;
1879
1880
18.9k
  rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
1881
18.9k
                                in_final);
1882
1883
18.9k
  if (rv < 0) {
1884
0
    return rv;
1885
0
  }
1886
1887
18.9k
  if (*inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
1888
16.5k
    nv_out->name = hd_nv.name->base;
1889
16.5k
    nv_out->namelen = hd_nv.name->len;
1890
1891
16.5k
    nv_out->value = hd_nv.value->base;
1892
16.5k
    nv_out->valuelen = hd_nv.value->len;
1893
1894
16.5k
    nv_out->flags = hd_nv.flags;
1895
16.5k
  }
1896
1897
18.9k
  return rv;
1898
18.9k
}
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
374k
                                       size_t inlen, int in_final) {
1904
374k
  nghttp2_ssize rv = 0;
1905
374k
  const uint8_t *first = in;
1906
374k
  const uint8_t *last = in + inlen;
1907
374k
  int rfin = 0;
1908
374k
  int busy = 0;
1909
374k
  nghttp2_mem *mem;
1910
1911
374k
  mem = inflater->ctx.mem;
1912
1913
374k
  if (inflater->ctx.bad) {
1914
0
    return NGHTTP2_ERR_HEADER_COMP;
1915
0
  }
1916
1917
374k
  DEBUGF("inflatehd: start state=%d\n", inflater->state);
1918
374k
  hd_inflate_keep_free(inflater);
1919
374k
  *inflate_flags = NGHTTP2_HD_INFLATE_NONE;
1920
1.16M
  for (; in != last || busy;) {
1921
1.12M
    busy = 0;
1922
1.12M
    switch (inflater->state) {
1923
23
    case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1924
23
      if ((*in & 0xe0u) != 0x20u) {
1925
3
        DEBUGF("inflatehd: header table size change was expected, but saw "
1926
3
               "0x%02x as first byte",
1927
3
               *in);
1928
3
        rv = NGHTTP2_ERR_HEADER_COMP;
1929
3
        goto fail;
1930
3
      }
1931
    /* fall through */
1932
37.9k
    case NGHTTP2_HD_STATE_INFLATE_START:
1933
336k
    case NGHTTP2_HD_STATE_OPCODE:
1934
336k
      if ((*in & 0xe0u) == 0x20u) {
1935
5.05k
        DEBUGF("inflatehd: header table size change\n");
1936
5.05k
        if (inflater->state == NGHTTP2_HD_STATE_OPCODE) {
1937
41
          DEBUGF("inflatehd: header table size change must appear at the head "
1938
41
                 "of header block\n");
1939
41
          rv = NGHTTP2_ERR_HEADER_COMP;
1940
41
          goto fail;
1941
41
        }
1942
5.00k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1943
5.00k
        inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
1944
331k
      } else if (*in & 0x80u) {
1945
163k
        DEBUGF("inflatehd: indexed repr\n");
1946
163k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1947
163k
        inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1948
168k
      } else {
1949
168k
        if (*in == 0x40u || *in == 0 || *in == 0x10u) {
1950
119k
          DEBUGF("inflatehd: literal header repr - new name\n");
1951
119k
          inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
1952
119k
          inflater->state = NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN;
1953
119k
        } else {
1954
49.0k
          DEBUGF("inflatehd: literal header repr - indexed name\n");
1955
49.0k
          inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
1956
49.0k
          inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1957
49.0k
        }
1958
168k
        inflater->index_required = (*in & 0x40) != 0;
1959
168k
        inflater->no_index = (*in & 0xf0u) == 0x10u;
1960
168k
        DEBUGF("inflatehd: indexing required=%d, no_index=%d\n",
1961
168k
               inflater->index_required, inflater->no_index);
1962
168k
        if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1963
119k
          ++in;
1964
119k
        }
1965
168k
      }
1966
336k
      inflater->left = 0;
1967
336k
      inflater->shift = 0;
1968
336k
      break;
1969
5.70k
    case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
1970
5.70k
      rfin = 0;
1971
5.70k
      rv = hd_inflate_read_len(
1972
5.70k
        inflater, &rfin, in, last, 5,
1973
5.70k
        nghttp2_min_size(inflater->min_hd_table_bufsize_max,
1974
5.70k
                         inflater->settings_hd_table_bufsize_max));
1975
5.70k
      if (rv < 0) {
1976
374
        goto fail;
1977
374
      }
1978
5.33k
      in += rv;
1979
5.33k
      if (!rfin) {
1980
780
        goto almost_ok;
1981
780
      }
1982
4.55k
      DEBUGF("inflatehd: table_size=%zu\n", inflater->left);
1983
4.55k
      inflater->min_hd_table_bufsize_max = UINT32_MAX;
1984
4.55k
      inflater->ctx.hd_table_bufsize_max = inflater->left;
1985
4.55k
      hd_context_shrink_table_size(&inflater->ctx, NULL);
1986
4.55k
      inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
1987
4.55k
      break;
1988
212k
    case NGHTTP2_HD_STATE_READ_INDEX: {
1989
212k
      size_t prefixlen;
1990
1991
212k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
1992
163k
        prefixlen = 7;
1993
163k
      } else if (inflater->index_required) {
1994
30.1k
        prefixlen = 6;
1995
30.1k
      } else {
1996
19.2k
        prefixlen = 4;
1997
19.2k
      }
1998
1999
212k
      rfin = 0;
2000
212k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
2001
212k
                               get_max_index(&inflater->ctx));
2002
212k
      if (rv < 0) {
2003
711
        goto fail;
2004
711
      }
2005
2006
211k
      in += rv;
2007
2008
211k
      if (!rfin) {
2009
430
        goto almost_ok;
2010
430
      }
2011
2012
211k
      if (inflater->left == 0) {
2013
16
        rv = NGHTTP2_ERR_HEADER_COMP;
2014
16
        goto fail;
2015
16
      }
2016
2017
211k
      DEBUGF("inflatehd: index=%zu\n", inflater->left);
2018
211k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
2019
162k
        inflater->index = inflater->left;
2020
162k
        --inflater->index;
2021
2022
162k
        hd_inflate_commit_indexed(inflater, nv_out);
2023
2024
162k
        inflater->state = NGHTTP2_HD_STATE_OPCODE;
2025
162k
        *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2026
162k
        return (nghttp2_ssize)(in - first);
2027
162k
      } else {
2028
48.7k
        inflater->index = inflater->left;
2029
48.7k
        --inflater->index;
2030
2031
48.7k
        inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2032
48.7k
      }
2033
48.7k
      break;
2034
211k
    }
2035
119k
    case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
2036
119k
      hd_inflate_set_huffman_encoded(inflater, in);
2037
119k
      inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
2038
119k
      inflater->left = 0;
2039
119k
      inflater->shift = 0;
2040
119k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2041
    /* Fall through */
2042
119k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN:
2043
119k
      rfin = 0;
2044
119k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2045
119k
      if (rv < 0) {
2046
313
        goto fail;
2047
313
      }
2048
119k
      in += rv;
2049
119k
      if (!rfin) {
2050
311
        DEBUGF("inflatehd: integer not fully decoded. current=%zu\n",
2051
311
               inflater->left);
2052
2053
311
        goto almost_ok;
2054
311
      }
2055
2056
118k
      if (inflater->huffman_encoded) {
2057
15.1k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2058
2059
15.1k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
2060
2061
15.1k
        rv =
2062
15.1k
          nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1, mem);
2063
103k
      } else {
2064
103k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
2065
103k
        rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
2066
103k
      }
2067
2068
118k
      if (rv != 0) {
2069
0
        goto fail;
2070
0
      }
2071
2072
118k
      nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base,
2073
118k
                            inflater->namercbuf->len);
2074
2075
118k
      break;
2076
15.1k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
2077
15.1k
      rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
2078
15.1k
      if (rv < 0) {
2079
21
        goto fail;
2080
21
      }
2081
2082
15.1k
      in += rv;
2083
2084
15.1k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2085
2086
15.1k
      if (inflater->left) {
2087
99
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2088
2089
99
        goto almost_ok;
2090
99
      }
2091
2092
15.0k
      *inflater->namebuf.last = '\0';
2093
15.0k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2094
2095
15.0k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2096
2097
15.0k
      break;
2098
103k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
2099
103k
      rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
2100
103k
      if (rv < 0) {
2101
0
        goto fail;
2102
0
      }
2103
2104
103k
      in += rv;
2105
2106
103k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2107
103k
      if (inflater->left) {
2108
142
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2109
2110
142
        goto almost_ok;
2111
142
      }
2112
2113
103k
      *inflater->namebuf.last = '\0';
2114
103k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2115
2116
103k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2117
2118
103k
      break;
2119
167k
    case NGHTTP2_HD_STATE_CHECK_VALUELEN:
2120
167k
      hd_inflate_set_huffman_encoded(inflater, in);
2121
167k
      inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
2122
167k
      inflater->left = 0;
2123
167k
      inflater->shift = 0;
2124
167k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2125
    /* Fall through */
2126
167k
    case NGHTTP2_HD_STATE_READ_VALUELEN:
2127
167k
      rfin = 0;
2128
167k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2129
167k
      if (rv < 0) {
2130
346
        goto fail;
2131
346
      }
2132
2133
167k
      in += rv;
2134
2135
167k
      if (!rfin) {
2136
379
        goto almost_ok;
2137
379
      }
2138
2139
166k
      DEBUGF("inflatehd: valuelen=%zu\n", inflater->left);
2140
2141
166k
      if (inflater->huffman_encoded) {
2142
22.6k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2143
2144
22.6k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
2145
2146
22.6k
        rv =
2147
22.6k
          nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1, mem);
2148
144k
      } else {
2149
144k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
2150
2151
144k
        rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem);
2152
144k
      }
2153
2154
166k
      if (rv != 0) {
2155
0
        goto fail;
2156
0
      }
2157
2158
166k
      nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base,
2159
166k
                            inflater->valuercbuf->len);
2160
2161
166k
      busy = 1;
2162
2163
166k
      break;
2164
22.6k
    case NGHTTP2_HD_STATE_READ_VALUEHUFF:
2165
22.6k
      rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
2166
22.6k
      if (rv < 0) {
2167
25
        goto fail;
2168
25
      }
2169
2170
22.6k
      in += rv;
2171
2172
22.6k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2173
2174
22.6k
      if (inflater->left) {
2175
162
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2176
2177
162
        goto almost_ok;
2178
162
      }
2179
2180
22.4k
      *inflater->valuebuf.last = '\0';
2181
22.4k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2182
2183
22.4k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2184
9.28k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2185
13.1k
      } else {
2186
13.1k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2187
13.1k
      }
2188
2189
22.4k
      if (rv != 0) {
2190
0
        goto fail;
2191
0
      }
2192
2193
22.4k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2194
22.4k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2195
2196
22.4k
      return (nghttp2_ssize)(in - first);
2197
144k
    case NGHTTP2_HD_STATE_READ_VALUE:
2198
144k
      rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
2199
144k
      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
144k
      in += rv;
2206
2207
144k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2208
2209
144k
      if (inflater->left) {
2210
250
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2211
250
        goto almost_ok;
2212
250
      }
2213
2214
143k
      *inflater->valuebuf.last = '\0';
2215
143k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2216
2217
143k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2218
109k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2219
109k
      } else {
2220
34.7k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2221
34.7k
      }
2222
2223
143k
      if (rv != 0) {
2224
0
        goto fail;
2225
0
      }
2226
2227
143k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2228
143k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2229
2230
143k
      return (nghttp2_ssize)(in - first);
2231
1.12M
    }
2232
1.12M
  }
2233
2234
374k
  assert(in == last);
2235
2236
40.8k
  DEBUGF("inflatehd: all input bytes were processed\n");
2237
2238
40.8k
  if (in_final) {
2239
27.8k
    DEBUGF("inflatehd: in_final set\n");
2240
2241
27.8k
    if (inflater->state != NGHTTP2_HD_STATE_OPCODE &&
2242
11.2k
        inflater->state != NGHTTP2_HD_STATE_INFLATE_START) {
2243
19
      DEBUGF("inflatehd: unacceptable state=%d\n", inflater->state);
2244
19
      rv = NGHTTP2_ERR_HEADER_COMP;
2245
2246
19
      goto fail;
2247
19
    }
2248
27.8k
    *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
2249
27.8k
  }
2250
40.8k
  return (nghttp2_ssize)(in - first);
2251
2252
2.55k
almost_ok:
2253
2.55k
  if (in_final) {
2254
23
    DEBUGF("inflatehd: input ended prematurely\n");
2255
2256
23
    rv = NGHTTP2_ERR_HEADER_COMP;
2257
2258
23
    goto fail;
2259
23
  }
2260
2.53k
  return (nghttp2_ssize)(in - first);
2261
2262
1.89k
fail:
2263
1.89k
  DEBUGF("inflatehd: error return %td\n", rv);
2264
2265
1.89k
  inflater->ctx.bad = 1;
2266
1.89k
  return rv;
2267
2.55k
}
2268
2269
27.8k
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
2270
27.8k
  hd_inflate_keep_free(inflater);
2271
27.8k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
2272
27.8k
  return 0;
2273
27.8k
}
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
}