Coverage Report

Created: 2025-10-13 06:27

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