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
58.4k
static int memeq(const void *s1, const void *s2, size_t n) {
114
58.4k
  return memcmp(s1, s2, n) == 0;
115
58.4k
}
116
117
/*
118
 * This function was generated by genlibtokenlookup.py.  Inspired by
119
 * h2o header lookup.  https://github.com/h2o/h2o
120
 */
121
94.0k
static int32_t lookup_token(const uint8_t *name, size_t namelen) {
122
94.0k
  switch (namelen) {
123
895
  case 2:
124
895
    switch (name[1]) {
125
565
    case 'e':
126
565
      if (memeq("t", name, 1)) {
127
343
        return NGHTTP2_TOKEN_TE;
128
343
      }
129
222
      break;
130
895
    }
131
552
    break;
132
1.85k
  case 3:
133
1.85k
    switch (name[2]) {
134
753
    case 'a':
135
753
      if (memeq("vi", name, 2)) {
136
194
        return NGHTTP2_TOKEN_VIA;
137
194
      }
138
559
      break;
139
582
    case 'e':
140
582
      if (memeq("ag", name, 2)) {
141
194
        return NGHTTP2_TOKEN_AGE;
142
194
      }
143
388
      break;
144
1.85k
    }
145
1.46k
    break;
146
6.27k
  case 4:
147
6.27k
    switch (name[3]) {
148
984
    case 'e':
149
984
      if (memeq("dat", name, 3)) {
150
342
        return NGHTTP2_TOKEN_DATE;
151
342
      }
152
642
      break;
153
642
    case 'g':
154
468
      if (memeq("eta", name, 3)) {
155
194
        return NGHTTP2_TOKEN_ETAG;
156
194
      }
157
274
      break;
158
1.41k
    case 'k':
159
1.41k
      if (memeq("lin", name, 3)) {
160
1.10k
        return NGHTTP2_TOKEN_LINK;
161
1.10k
      }
162
310
      break;
163
451
    case 'm':
164
451
      if (memeq("fro", name, 3)) {
165
194
        return NGHTTP2_TOKEN_FROM;
166
194
      }
167
257
      break;
168
718
    case 't':
169
718
      if (memeq("hos", name, 3)) {
170
349
        return NGHTTP2_TOKEN_HOST;
171
349
      }
172
369
      break;
173
623
    case 'y':
174
623
      if (memeq("var", name, 3)) {
175
217
        return NGHTTP2_TOKEN_VARY;
176
217
      }
177
406
      break;
178
6.27k
    }
179
3.87k
    break;
180
3.87k
  case 5:
181
1.91k
    switch (name[4]) {
182
579
    case 'e':
183
579
      if (memeq("rang", name, 4)) {
184
299
        return NGHTTP2_TOKEN_RANGE;
185
299
      }
186
280
      break;
187
464
    case 'h':
188
464
      if (memeq(":pat", name, 4)) {
189
258
        return NGHTTP2_TOKEN__PATH;
190
258
      }
191
206
      break;
192
391
    case 'w':
193
391
      if (memeq("allo", name, 4)) {
194
194
        return NGHTTP2_TOKEN_ALLOW;
195
194
      }
196
197
      break;
197
1.91k
    }
198
1.16k
    break;
199
2.13k
  case 6:
200
2.13k
    switch (name[5]) {
201
399
    case 'e':
202
399
      if (memeq("cooki", name, 5)) {
203
194
        return NGHTTP2_TOKEN_COOKIE;
204
194
      }
205
205
      break;
206
409
    case 'r':
207
409
      if (memeq("serve", name, 5)) {
208
194
        return NGHTTP2_TOKEN_SERVER;
209
194
      }
210
215
      break;
211
873
    case 't':
212
873
      if (memeq("accep", name, 5)) {
213
424
        return NGHTTP2_TOKEN_ACCEPT;
214
424
      }
215
449
      if (memeq("expec", name, 5)) {
216
217
        return NGHTTP2_TOKEN_EXPECT;
217
217
      }
218
232
      break;
219
2.13k
    }
220
1.11k
    break;
221
14.9k
  case 7:
222
14.9k
    switch (name[6]) {
223
1.10k
    case 'd':
224
1.10k
      if (memeq(":metho", name, 6)) {
225
545
        return NGHTTP2_TOKEN__METHOD;
226
545
      }
227
561
      break;
228
8.76k
    case 'e':
229
8.76k
      if (memeq(":schem", name, 6)) {
230
194
        return NGHTTP2_TOKEN__SCHEME;
231
194
      }
232
8.56k
      if (memeq("upgrad", name, 6)) {
233
7.68k
        return NGHTTP2_TOKEN_UPGRADE;
234
7.68k
      }
235
880
      break;
236
2.01k
    case 'h':
237
2.01k
      if (memeq("refres", name, 6)) {
238
1.79k
        return NGHTTP2_TOKEN_REFRESH;
239
1.79k
      }
240
225
      break;
241
551
    case 'r':
242
551
      if (memeq("refere", name, 6)) {
243
194
        return NGHTTP2_TOKEN_REFERER;
244
194
      }
245
357
      break;
246
611
    case 's':
247
611
      if (memeq(":statu", name, 6)) {
248
195
        return NGHTTP2_TOKEN__STATUS;
249
195
      }
250
416
      if (memeq("expire", name, 6)) {
251
194
        return NGHTTP2_TOKEN_EXPIRES;
252
194
      }
253
222
      break;
254
14.9k
    }
255
4.18k
    break;
256
6.60k
  case 8:
257
6.60k
    switch (name[7]) {
258
657
    case 'e':
259
657
      if (memeq("if-rang", name, 7)) {
260
209
        return NGHTTP2_TOKEN_IF_RANGE;
261
209
      }
262
448
      break;
263
448
    case 'h':
264
400
      if (memeq("if-matc", name, 7)) {
265
197
        return NGHTTP2_TOKEN_IF_MATCH;
266
197
      }
267
203
      break;
268
412
    case 'n':
269
412
      if (memeq("locatio", name, 7)) {
270
217
        return NGHTTP2_TOKEN_LOCATION;
271
217
      }
272
195
      break;
273
4.86k
    case 'y':
274
4.86k
      if (memeq("priorit", name, 7)) {
275
4.65k
        return NGHTTP2_TOKEN_PRIORITY;
276
4.65k
      }
277
207
      break;
278
6.60k
    }
279
1.32k
    break;
280
1.42k
  case 9:
281
1.42k
    switch (name[8]) {
282
1.02k
    case 'l':
283
1.02k
      if (memeq(":protoco", name, 8)) {
284
769
        return NGHTTP2_TOKEN__PROTOCOL;
285
769
      }
286
251
      break;
287
1.42k
    }
288
659
    break;
289
4.24k
  case 10:
290
4.24k
    switch (name[9]) {
291
1.58k
    case 'e':
292
1.58k
      if (memeq("keep-aliv", name, 9)) {
293
656
        return NGHTTP2_TOKEN_KEEP_ALIVE;
294
656
      }
295
929
      if (memeq("set-cooki", name, 9)) {
296
194
        return NGHTTP2_TOKEN_SET_COOKIE;
297
194
      }
298
735
      break;
299
735
    case 'n':
300
505
      if (memeq("connectio", name, 9)) {
301
241
        return NGHTTP2_TOKEN_CONNECTION;
302
241
      }
303
264
      break;
304
464
    case 't':
305
464
      if (memeq("user-agen", name, 9)) {
306
225
        return NGHTTP2_TOKEN_USER_AGENT;
307
225
      }
308
239
      break;
309
737
    case 'y':
310
737
      if (memeq(":authorit", name, 9)) {
311
244
        return NGHTTP2_TOKEN__AUTHORITY;
312
244
      }
313
493
      break;
314
4.24k
    }
315
2.68k
    break;
316
2.68k
  case 11:
317
1.09k
    switch (name[10]) {
318
880
    case 'r':
319
880
      if (memeq("retry-afte", name, 10)) {
320
514
        return NGHTTP2_TOKEN_RETRY_AFTER;
321
514
      }
322
366
      break;
323
1.09k
    }
324
580
    break;
325
1.35k
  case 12:
326
1.35k
    switch (name[11]) {
327
454
    case 'e':
328
454
      if (memeq("content-typ", name, 11)) {
329
211
        return NGHTTP2_TOKEN_CONTENT_TYPE;
330
211
      }
331
243
      break;
332
425
    case 's':
333
425
      if (memeq("max-forward", name, 11)) {
334
194
        return NGHTTP2_TOKEN_MAX_FORWARDS;
335
194
      }
336
231
      break;
337
1.35k
    }
338
945
    break;
339
2.88k
  case 13:
340
2.88k
    switch (name[12]) {
341
460
    case 'd':
342
460
      if (memeq("last-modifie", name, 12)) {
343
243
        return NGHTTP2_TOKEN_LAST_MODIFIED;
344
243
      }
345
217
      break;
346
306
    case 'e':
347
306
      if (memeq("content-rang", name, 12)) {
348
67
        return NGHTTP2_TOKEN_CONTENT_RANGE;
349
67
      }
350
239
      break;
351
426
    case 'h':
352
426
      if (memeq("if-none-matc", name, 12)) {
353
208
        return NGHTTP2_TOKEN_IF_NONE_MATCH;
354
208
      }
355
218
      break;
356
533
    case 'l':
357
533
      if (memeq("cache-contro", name, 12)) {
358
218
        return NGHTTP2_TOKEN_CACHE_CONTROL;
359
218
      }
360
315
      break;
361
403
    case 'n':
362
403
      if (memeq("authorizatio", name, 12)) {
363
194
        return NGHTTP2_TOKEN_AUTHORIZATION;
364
194
      }
365
209
      break;
366
415
    case 's':
367
415
      if (memeq("accept-range", name, 12)) {
368
198
        return NGHTTP2_TOKEN_ACCEPT_RANGES;
369
198
      }
370
217
      break;
371
2.88k
    }
372
1.75k
    break;
373
1.75k
  case 14:
374
1.48k
    switch (name[13]) {
375
634
    case 'h':
376
634
      if (memeq("content-lengt", name, 13)) {
377
194
        return NGHTTP2_TOKEN_CONTENT_LENGTH;
378
194
      }
379
440
      break;
380
539
    case 't':
381
539
      if (memeq("accept-charse", name, 13)) {
382
194
        return NGHTTP2_TOKEN_ACCEPT_CHARSET;
383
194
      }
384
345
      break;
385
1.48k
    }
386
1.09k
    break;
387
1.33k
  case 15:
388
1.33k
    switch (name[14]) {
389
642
    case 'e':
390
642
      if (memeq("accept-languag", name, 14)) {
391
311
        return NGHTTP2_TOKEN_ACCEPT_LANGUAGE;
392
311
      }
393
331
      break;
394
411
    case 'g':
395
411
      if (memeq("accept-encodin", name, 14)) {
396
196
        return NGHTTP2_TOKEN_ACCEPT_ENCODING;
397
196
      }
398
215
      break;
399
1.33k
    }
400
825
    break;
401
2.80k
  case 16:
402
2.80k
    switch (name[15]) {
403
1.11k
    case 'e':
404
1.11k
      if (memeq("content-languag", name, 15)) {
405
309
        return NGHTTP2_TOKEN_CONTENT_LANGUAGE;
406
309
      }
407
804
      if (memeq("www-authenticat", name, 15)) {
408
341
        return NGHTTP2_TOKEN_WWW_AUTHENTICATE;
409
341
      }
410
463
      break;
411
463
    case 'g':
412
439
      if (memeq("content-encodin", name, 15)) {
413
197
        return NGHTTP2_TOKEN_CONTENT_ENCODING;
414
197
      }
415
242
      break;
416
776
    case 'n':
417
776
      if (memeq("content-locatio", name, 15)) {
418
195
        return NGHTTP2_TOKEN_CONTENT_LOCATION;
419
195
      }
420
581
      if (memeq("proxy-connectio", name, 15)) {
421
308
        return NGHTTP2_TOKEN_PROXY_CONNECTION;
422
308
      }
423
273
      break;
424
2.80k
    }
425
1.45k
    break;
426
1.45k
  case 17:
427
1.36k
    switch (name[16]) {
428
421
    case 'e':
429
421
      if (memeq("if-modified-sinc", name, 16)) {
430
194
        return NGHTTP2_TOKEN_IF_MODIFIED_SINCE;
431
194
      }
432
227
      break;
433
535
    case 'g':
434
535
      if (memeq("transfer-encodin", name, 16)) {
435
337
        return NGHTTP2_TOKEN_TRANSFER_ENCODING;
436
337
      }
437
198
      break;
438
1.36k
    }
439
838
    break;
440
1.29k
  case 18:
441
1.29k
    switch (name[17]) {
442
1.00k
    case 'e':
443
1.00k
      if (memeq("proxy-authenticat", name, 17)) {
444
206
        return NGHTTP2_TOKEN_PROXY_AUTHENTICATE;
445
206
      }
446
796
      break;
447
1.29k
    }
448
1.08k
    break;
449
2.31k
  case 19:
450
2.31k
    switch (name[18]) {
451
619
    case 'e':
452
619
      if (memeq("if-unmodified-sinc", name, 18)) {
453
198
        return NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE;
454
198
      }
455
421
      break;
456
637
    case 'n':
457
637
      if (memeq("content-dispositio", name, 18)) {
458
214
        return NGHTTP2_TOKEN_CONTENT_DISPOSITION;
459
214
      }
460
423
      if (memeq("proxy-authorizatio", name, 18)) {
461
197
        return NGHTTP2_TOKEN_PROXY_AUTHORIZATION;
462
197
      }
463
226
      break;
464
2.31k
    }
465
1.71k
    break;
466
1.71k
  case 25:
467
665
    switch (name[24]) {
468
425
    case 'y':
469
425
      if (memeq("strict-transport-securit", name, 24)) {
470
194
        return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY;
471
194
      }
472
231
      break;
473
665
    }
474
471
    break;
475
664
  case 27:
476
664
    switch (name[26]) {
477
403
    case 'n':
478
403
      if (memeq("access-control-allow-origi", name, 26)) {
479
194
        return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
480
194
      }
481
209
      break;
482
664
    }
483
470
    break;
484
94.0k
  }
485
64.7k
  return -1;
486
94.0k
}
487
488
27.7k
void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv) {
489
27.7k
  ent->nv = *nv;
490
27.7k
  ent->cnv.name = nv->name->base;
491
27.7k
  ent->cnv.namelen = nv->name->len;
492
27.7k
  ent->cnv.value = nv->value->base;
493
27.7k
  ent->cnv.valuelen = nv->value->len;
494
27.7k
  ent->cnv.flags = nv->flags;
495
27.7k
  ent->next = NULL;
496
27.7k
  ent->hash = 0;
497
498
27.7k
  nghttp2_rcbuf_incref(ent->nv.name);
499
27.7k
  nghttp2_rcbuf_incref(ent->nv.value);
500
27.7k
}
501
502
27.7k
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) {
503
27.7k
  nghttp2_rcbuf_decref(ent->nv.value);
504
27.7k
  nghttp2_rcbuf_decref(ent->nv.name);
505
27.7k
}
506
507
0
static int name_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
508
0
  return a->name->len == b->namelen &&
509
0
         memeq(a->name->base, b->name, b->namelen);
510
0
}
511
512
0
static int value_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
513
0
  return a->value->len == b->valuelen &&
514
0
         memeq(a->value->base, b->value, b->valuelen);
515
0
}
516
517
0
static uint32_t name_hash(const nghttp2_nv *nv) {
518
  /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */
519
0
  uint32_t h = 2166136261u;
520
0
  size_t i;
521
522
0
  for (i = 0; i < nv->namelen; ++i) {
523
0
    h ^= nv->name[i];
524
0
    h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
525
0
  }
526
527
0
  return h;
528
0
}
529
530
12.1k
static void hd_map_init(nghttp2_hd_map *map) {
531
12.1k
  memset(map, 0, sizeof(nghttp2_hd_map));
532
12.1k
}
533
534
0
static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
535
0
  nghttp2_hd_entry **bucket;
536
537
0
  bucket = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
538
539
0
  if (*bucket == NULL) {
540
0
    *bucket = ent;
541
0
    return;
542
0
  }
543
544
  /* lower index is linked near the root */
545
0
  ent->next = *bucket;
546
0
  *bucket = ent;
547
0
}
548
549
static nghttp2_hd_entry *hd_map_find(nghttp2_hd_map *map, int *exact_match,
550
                                     const nghttp2_nv *nv, int32_t token,
551
0
                                     uint32_t hash, int name_only) {
552
0
  nghttp2_hd_entry *p;
553
0
  nghttp2_hd_entry *res = NULL;
554
555
0
  *exact_match = 0;
556
557
0
  for (p = map->table[hash & (HD_MAP_SIZE - 1)]; p; p = p->next) {
558
0
    if (token != p->nv.token ||
559
0
        (token == -1 && (hash != p->hash || !name_eq(&p->nv, nv)))) {
560
0
      continue;
561
0
    }
562
0
    if (!res) {
563
0
      res = p;
564
0
      if (name_only) {
565
0
        break;
566
0
      }
567
0
    }
568
0
    if (value_eq(&p->nv, nv)) {
569
0
      res = p;
570
0
      *exact_match = 1;
571
0
      break;
572
0
    }
573
0
  }
574
575
0
  return res;
576
0
}
577
578
0
static void hd_map_remove(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
579
0
  nghttp2_hd_entry **dst;
580
581
0
  dst = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
582
583
0
  for (; *dst; dst = &(*dst)->next) {
584
0
    if (*dst != ent) {
585
0
      continue;
586
0
    }
587
588
0
    *dst = ent->next;
589
0
    ent->next = NULL;
590
0
    return;
591
0
  }
592
0
}
593
594
static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
595
24.2k
                           nghttp2_mem *mem) {
596
24.2k
  size_t size;
597
24.2k
  const size_t max_size = SIZE_MAX / sizeof(nghttp2_hd_entry *);
598
599
24.2k
  if (bufsize > max_size) {
600
0
    return NGHTTP2_ERR_NOMEM;
601
0
  }
602
603
193k
  for (size = 1; size < bufsize; size <<= 1)
604
169k
    ;
605
606
24.2k
  if (size > max_size) {
607
0
    return NGHTTP2_ERR_NOMEM;
608
0
  }
609
610
24.2k
  ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
611
24.2k
  if (ringbuf->buffer == NULL) {
612
0
    return NGHTTP2_ERR_NOMEM;
613
0
  }
614
24.2k
  ringbuf->mask = size - 1;
615
24.2k
  ringbuf->first = 0;
616
24.2k
  ringbuf->len = 0;
617
24.2k
  return 0;
618
24.2k
}
619
620
static nghttp2_hd_entry *hd_ringbuf_get(nghttp2_hd_ringbuf *ringbuf,
621
64.4k
                                        size_t idx) {
622
64.4k
  assert(idx < ringbuf->len);
623
64.4k
  return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask];
624
64.4k
}
625
626
static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
627
27.7k
                              nghttp2_mem *mem) {
628
27.7k
  size_t i;
629
27.7k
  size_t size;
630
27.7k
  nghttp2_hd_entry **buffer;
631
632
27.7k
  if (ringbuf->mask + 1 >= bufsize) {
633
27.7k
    return 0;
634
27.7k
  }
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
24.2k
static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
652
24.2k
  size_t i;
653
24.2k
  if (ringbuf == NULL) {
654
0
    return;
655
0
  }
656
42.0k
  for (i = 0; i < ringbuf->len; ++i) {
657
17.8k
    nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
658
659
17.8k
    nghttp2_hd_entry_free(ent);
660
17.8k
    nghttp2_mem_free(mem, ent);
661
17.8k
  }
662
24.2k
  nghttp2_mem_free(mem, ringbuf->buffer);
663
24.2k
}
664
665
static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf,
666
27.7k
                                 nghttp2_hd_entry *ent, nghttp2_mem *mem) {
667
27.7k
  int rv;
668
669
27.7k
  rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem);
670
671
27.7k
  if (rv != 0) {
672
0
    return rv;
673
0
  }
674
675
27.7k
  ringbuf->buffer[--ringbuf->first & ringbuf->mask] = ent;
676
27.7k
  ++ringbuf->len;
677
678
27.7k
  return 0;
679
27.7k
}
680
681
9.91k
static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) {
682
9.91k
  assert(ringbuf->len > 0);
683
9.91k
  --ringbuf->len;
684
9.91k
}
685
686
24.2k
static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
687
24.2k
  int rv;
688
24.2k
  context->mem = mem;
689
24.2k
  context->bad = 0;
690
24.2k
  context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
691
24.2k
  rv = hd_ringbuf_init(
692
24.2k
    &context->hd_table,
693
24.2k
    context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
694
24.2k
  if (rv != 0) {
695
0
    return rv;
696
0
  }
697
698
24.2k
  context->hd_table_bufsize = 0;
699
24.2k
  context->next_seq = 0;
700
701
24.2k
  return 0;
702
24.2k
}
703
704
24.2k
static void hd_context_free(nghttp2_hd_context *context) {
705
24.2k
  hd_ringbuf_free(&context->hd_table, context->mem);
706
24.2k
}
707
708
0
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) {
709
0
  return nghttp2_hd_deflate_init2(
710
0
    deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem);
711
0
}
712
713
int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
714
                             size_t max_deflate_dynamic_table_size,
715
12.1k
                             nghttp2_mem *mem) {
716
12.1k
  int rv;
717
12.1k
  rv = hd_context_init(&deflater->ctx, mem);
718
12.1k
  if (rv != 0) {
719
0
    return rv;
720
0
  }
721
722
12.1k
  hd_map_init(&deflater->map);
723
724
12.1k
  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
12.1k
  } else {
728
12.1k
    deflater->notify_table_size_change = 0;
729
12.1k
  }
730
731
12.1k
  deflater->deflate_hd_table_bufsize_max = max_deflate_dynamic_table_size;
732
12.1k
  deflater->min_hd_table_bufsize_max = UINT32_MAX;
733
734
12.1k
  return 0;
735
12.1k
}
736
737
12.1k
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
738
12.1k
  int rv;
739
740
12.1k
  rv = hd_context_init(&inflater->ctx, mem);
741
12.1k
  if (rv != 0) {
742
0
    goto fail;
743
0
  }
744
745
12.1k
  inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
746
12.1k
  inflater->min_hd_table_bufsize_max = UINT32_MAX;
747
748
12.1k
  inflater->nv_name_keep = NULL;
749
12.1k
  inflater->nv_value_keep = NULL;
750
751
12.1k
  inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
752
12.1k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
753
754
12.1k
  nghttp2_buf_init(&inflater->namebuf);
755
12.1k
  nghttp2_buf_init(&inflater->valuebuf);
756
757
12.1k
  inflater->namercbuf = NULL;
758
12.1k
  inflater->valuercbuf = NULL;
759
760
12.1k
  inflater->huffman_encoded = 0;
761
12.1k
  inflater->index = 0;
762
12.1k
  inflater->left = 0;
763
12.1k
  inflater->shift = 0;
764
12.1k
  inflater->index_required = 0;
765
12.1k
  inflater->no_index = 0;
766
767
12.1k
  return 0;
768
769
0
fail:
770
0
  return rv;
771
12.1k
}
772
773
302k
static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
774
302k
  nghttp2_rcbuf_decref(inflater->nv_value_keep);
775
302k
  nghttp2_rcbuf_decref(inflater->nv_name_keep);
776
777
302k
  inflater->nv_value_keep = NULL;
778
302k
  inflater->nv_name_keep = NULL;
779
302k
}
780
781
12.1k
void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
782
12.1k
  hd_context_free(&deflater->ctx);
783
12.1k
}
784
785
12.1k
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
786
12.1k
  hd_inflate_keep_free(inflater);
787
788
12.1k
  nghttp2_rcbuf_decref(inflater->valuercbuf);
789
12.1k
  nghttp2_rcbuf_decref(inflater->namercbuf);
790
791
12.1k
  hd_context_free(&inflater->ctx);
792
12.1k
}
793
794
38.6k
static size_t entry_room(size_t namelen, size_t valuelen) {
795
38.6k
  return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
796
38.6k
}
797
798
241k
static void emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
799
241k
  DEBUGF("inflatehd: header emission: %s: %s\n", nv->name->base,
800
241k
         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
241k
  *nv_out = *nv;
804
241k
}
805
806
0
static size_t count_encoded_length(size_t n, size_t prefix) {
807
0
  size_t k = (size_t)((1 << prefix) - 1);
808
0
  size_t len = 0;
809
810
0
  if (n < k) {
811
0
    return 1;
812
0
  }
813
814
0
  n -= k;
815
0
  ++len;
816
817
0
  for (; n >= 128; n >>= 7, ++len)
818
0
    ;
819
820
0
  return len + 1;
821
0
}
822
823
0
static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
824
0
  size_t k = (size_t)((1 << prefix) - 1);
825
0
  uint8_t *begin = buf;
826
827
0
  *buf = (uint8_t)(*buf & ~k);
828
829
0
  if (n < k) {
830
0
    *buf = (uint8_t)(*buf | n);
831
0
    return 1;
832
0
  }
833
834
0
  *buf = (uint8_t)(*buf | k);
835
0
  ++buf;
836
837
0
  n -= k;
838
839
0
  for (; n >= 128; n >>= 7) {
840
0
    *buf++ = (uint8_t)((1 << 7) | (n & 0x7f));
841
0
  }
842
843
0
  *buf++ = (uint8_t)n;
844
845
0
  return (size_t)(buf - begin);
846
0
}
847
848
/*
849
 * Decodes |prefix| prefixed integer stored from |in|.  The |last|
850
 * represents the 1 beyond the last of the valid contiguous memory
851
 * region from |in|.  The decoded integer must be less than or equal
852
 * to UINT32_MAX.
853
 *
854
 * If the |initial| is nonzero, it is used as a initial value, this
855
 * function assumes the |in| starts with intermediate data.
856
 *
857
 * An entire integer is decoded successfully, decoded, the |*fin| is
858
 * set to nonzero.
859
 *
860
 * This function stores the decoded integer in |*res| if it succeed,
861
 * including partial decoding (in this case, number of shift to make
862
 * in the next call will be stored in |*shift_ptr|) and returns number
863
 * of bytes processed, or returns -1, indicating decoding error.
864
 */
865
static nghttp2_ssize decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
866
                                   uint32_t initial, size_t shift,
867
                                   const uint8_t *in, const uint8_t *last,
868
375k
                                   size_t prefix) {
869
375k
  uint32_t k = (uint8_t)((1 << prefix) - 1);
870
375k
  uint32_t n = initial;
871
375k
  const uint8_t *start = in;
872
873
375k
  *shift_ptr = 0;
874
375k
  *fin = 0;
875
876
375k
  if (n == 0) {
877
374k
    if ((*in & k) != k) {
878
367k
      *res = (*in) & k;
879
367k
      *fin = 1;
880
367k
      return 1;
881
367k
    }
882
883
6.76k
    n = k;
884
885
6.76k
    if (++in == last) {
886
134
      *res = n;
887
134
      return (nghttp2_ssize)(in - start);
888
134
    }
889
6.76k
  }
890
891
20.3k
  for (; in != last; ++in, shift += 7) {
892
19.0k
    uint32_t add = *in & 0x7f;
893
894
19.0k
    if (shift >= 32) {
895
26
      DEBUGF("inflate: shift exponent overflow\n");
896
26
      return -1;
897
26
    }
898
899
18.9k
    if ((UINT32_MAX >> shift) < add) {
900
42
      DEBUGF("inflate: integer overflow on shift\n");
901
42
      return -1;
902
42
    }
903
904
18.9k
    add <<= shift;
905
906
18.9k
    if (UINT32_MAX - add < n) {
907
45
      DEBUGF("inflate: integer overflow on addition\n");
908
45
      return -1;
909
45
    }
910
911
18.9k
    n += add;
912
913
18.9k
    if ((*in & (1 << 7)) == 0) {
914
6.13k
      break;
915
6.13k
    }
916
18.9k
  }
917
918
7.46k
  *shift_ptr = shift;
919
920
7.46k
  if (in == last) {
921
1.33k
    *res = n;
922
1.33k
    return (nghttp2_ssize)(in - start);
923
1.33k
  }
924
925
6.13k
  *res = n;
926
6.13k
  *fin = 1;
927
6.13k
  return (nghttp2_ssize)(in + 1 - start);
928
7.46k
}
929
930
0
static int emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
931
0
  int rv;
932
0
  uint8_t *bufp;
933
0
  size_t blocklen;
934
0
  uint8_t sb[16];
935
936
0
  DEBUGF("deflatehd: emit table_size=%zu\n", table_size);
937
938
0
  blocklen = count_encoded_length(table_size, 5);
939
940
0
  if (sizeof(sb) < blocklen) {
941
0
    return NGHTTP2_ERR_HEADER_COMP;
942
0
  }
943
944
0
  bufp = sb;
945
946
0
  *bufp = 0x20u;
947
948
0
  encode_length(bufp, table_size, 5);
949
950
0
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
951
0
  if (rv != 0) {
952
0
    return rv;
953
0
  }
954
955
0
  return 0;
956
0
}
957
958
0
static int emit_indexed_block(nghttp2_bufs *bufs, size_t idx) {
959
0
  int rv;
960
0
  size_t blocklen;
961
0
  uint8_t sb[16];
962
0
  uint8_t *bufp;
963
964
0
  blocklen = count_encoded_length(idx + 1, 7);
965
966
0
  DEBUGF("deflatehd: emit indexed index=%zu, %zu bytes\n", idx, blocklen);
967
968
0
  if (sizeof(sb) < blocklen) {
969
0
    return NGHTTP2_ERR_HEADER_COMP;
970
0
  }
971
972
0
  bufp = sb;
973
0
  *bufp = 0x80u;
974
0
  encode_length(bufp, idx + 1, 7);
975
976
0
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
977
0
  if (rv != 0) {
978
0
    return rv;
979
0
  }
980
981
0
  return 0;
982
0
}
983
984
0
static int emit_string(nghttp2_bufs *bufs, const uint8_t *str, size_t len) {
985
0
  int rv;
986
0
  uint8_t sb[16];
987
0
  uint8_t *bufp;
988
0
  size_t blocklen;
989
0
  size_t enclen;
990
0
  int huffman = 0;
991
992
0
  enclen = nghttp2_hd_huff_encode_count(str, len);
993
994
0
  if (enclen < len) {
995
0
    huffman = 1;
996
0
  } else {
997
0
    enclen = len;
998
0
  }
999
1000
0
  blocklen = count_encoded_length(enclen, 7);
1001
1002
0
  DEBUGF("deflatehd: emit string str=%.*s, length=%zu, huffman=%d, "
1003
0
         "encoded_length=%zu\n",
1004
0
         (int)len, (const char *)str, len, huffman, enclen);
1005
1006
0
  if (sizeof(sb) < blocklen) {
1007
0
    return NGHTTP2_ERR_HEADER_COMP;
1008
0
  }
1009
1010
0
  bufp = sb;
1011
0
  *bufp = huffman ? 1 << 7 : 0;
1012
0
  encode_length(bufp, enclen, 7);
1013
1014
0
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
1015
0
  if (rv != 0) {
1016
0
    return rv;
1017
0
  }
1018
1019
0
  if (huffman) {
1020
0
    rv = nghttp2_hd_huff_encode(bufs, str, len);
1021
0
  } else {
1022
0
    assert(enclen == len);
1023
0
    rv = nghttp2_bufs_add(bufs, str, len);
1024
0
  }
1025
1026
0
  return rv;
1027
0
}
1028
1029
0
static uint8_t pack_first_byte(int indexing_mode) {
1030
0
  switch (indexing_mode) {
1031
0
  case NGHTTP2_HD_WITH_INDEXING:
1032
0
    return 0x40u;
1033
0
  case NGHTTP2_HD_WITHOUT_INDEXING:
1034
0
    return 0;
1035
0
  case NGHTTP2_HD_NEVER_INDEXING:
1036
0
    return 0x10u;
1037
0
  default:
1038
0
    assert(0);
1039
0
  }
1040
  /* This is required to compile with android NDK r10d +
1041
     --enable-werror */
1042
0
  return 0;
1043
0
}
1044
1045
static int emit_indname_block(nghttp2_bufs *bufs, size_t idx,
1046
0
                              const nghttp2_nv *nv, int indexing_mode) {
1047
0
  int rv;
1048
0
  uint8_t *bufp;
1049
0
  size_t blocklen;
1050
0
  uint8_t sb[16];
1051
0
  size_t prefixlen;
1052
1053
0
  if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1054
0
    prefixlen = 6;
1055
0
  } else {
1056
0
    prefixlen = 4;
1057
0
  }
1058
1059
0
  DEBUGF("deflatehd: emit indname index=%zu, valuelen=%zu, indexing_mode=%d\n",
1060
0
         idx, nv->valuelen, indexing_mode);
1061
1062
0
  blocklen = count_encoded_length(idx + 1, prefixlen);
1063
1064
0
  if (sizeof(sb) < blocklen) {
1065
0
    return NGHTTP2_ERR_HEADER_COMP;
1066
0
  }
1067
1068
0
  bufp = sb;
1069
1070
0
  *bufp = pack_first_byte(indexing_mode);
1071
1072
0
  encode_length(bufp, idx + 1, prefixlen);
1073
1074
0
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
1075
0
  if (rv != 0) {
1076
0
    return rv;
1077
0
  }
1078
1079
0
  rv = emit_string(bufs, nv->value, nv->valuelen);
1080
0
  if (rv != 0) {
1081
0
    return rv;
1082
0
  }
1083
1084
0
  return 0;
1085
0
}
1086
1087
static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
1088
0
                              int indexing_mode) {
1089
0
  int rv;
1090
1091
0
  DEBUGF(
1092
0
    "deflatehd: emit newname namelen=%zu, valuelen=%zu, indexing_mode=%d\n",
1093
0
    nv->namelen, nv->valuelen, indexing_mode);
1094
1095
0
  rv = nghttp2_bufs_addb(bufs, pack_first_byte(indexing_mode));
1096
0
  if (rv != 0) {
1097
0
    return rv;
1098
0
  }
1099
1100
0
  rv = emit_string(bufs, nv->name, nv->namelen);
1101
0
  if (rv != 0) {
1102
0
    return rv;
1103
0
  }
1104
1105
0
  rv = emit_string(bufs, nv->value, nv->valuelen);
1106
0
  if (rv != 0) {
1107
0
    return rv;
1108
0
  }
1109
1110
0
  return 0;
1111
0
}
1112
1113
static int add_hd_table_incremental(nghttp2_hd_context *context,
1114
                                    nghttp2_hd_nv *nv, nghttp2_hd_map *map,
1115
28.7k
                                    uint32_t hash) {
1116
28.7k
  int rv;
1117
28.7k
  nghttp2_hd_entry *new_ent;
1118
28.7k
  size_t room;
1119
28.7k
  nghttp2_mem *mem;
1120
1121
28.7k
  mem = context->mem;
1122
28.7k
  room = entry_room(nv->name->len, nv->value->len);
1123
1124
37.9k
  while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
1125
10.2k
         context->hd_table.len > 0) {
1126
9.19k
    size_t idx = context->hd_table.len - 1;
1127
9.19k
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1128
1129
9.19k
    context->hd_table_bufsize -=
1130
9.19k
      entry_room(ent->nv.name->len, ent->nv.value->len);
1131
1132
9.19k
    DEBUGF("hpack: remove item from header table: %s: %s\n",
1133
9.19k
           (char *)ent->nv.name->base, (char *)ent->nv.value->base);
1134
1135
9.19k
    hd_ringbuf_pop_back(&context->hd_table);
1136
9.19k
    if (map) {
1137
0
      hd_map_remove(map, ent);
1138
0
    }
1139
1140
9.19k
    nghttp2_hd_entry_free(ent);
1141
9.19k
    nghttp2_mem_free(mem, ent);
1142
9.19k
  }
1143
1144
28.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.01k
    return 0;
1148
1.01k
  }
1149
1150
27.7k
  new_ent = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry));
1151
27.7k
  if (new_ent == NULL) {
1152
0
    return NGHTTP2_ERR_NOMEM;
1153
0
  }
1154
1155
27.7k
  nghttp2_hd_entry_init(new_ent, nv);
1156
1157
27.7k
  rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
1158
1159
27.7k
  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
27.7k
  new_ent->seq = context->next_seq++;
1167
27.7k
  new_ent->hash = hash;
1168
1169
27.7k
  if (map) {
1170
0
    hd_map_insert(map, new_ent);
1171
0
  }
1172
1173
27.7k
  context->hd_table_bufsize += room;
1174
1175
27.7k
  return 0;
1176
27.7k
}
1177
1178
typedef struct {
1179
  nghttp2_ssize index;
1180
  /* Nonzero if both name and value are matched. */
1181
  int name_value_match;
1182
} search_result;
1183
1184
static search_result search_static_table(const nghttp2_nv *nv, int32_t token,
1185
0
                                         int name_only) {
1186
0
  search_result res = {token, 0};
1187
0
  int i;
1188
0
  const nghttp2_hd_static_entry *ent;
1189
1190
0
  if (name_only) {
1191
0
    return res;
1192
0
  }
1193
1194
0
  for (i = token;
1195
0
       i <= NGHTTP2_TOKEN_WWW_AUTHENTICATE && static_table[i].token == token;
1196
0
       ++i) {
1197
0
    ent = &static_table[i];
1198
0
    if (ent->value.len == nv->valuelen &&
1199
0
        memcmp(ent->value.base, nv->value, nv->valuelen) == 0) {
1200
0
      res.index = i;
1201
0
      res.name_value_match = 1;
1202
0
      return res;
1203
0
    }
1204
0
  }
1205
0
  return res;
1206
0
}
1207
1208
static search_result search_hd_table(nghttp2_hd_context *context,
1209
                                     const nghttp2_nv *nv, int32_t token,
1210
                                     int indexing_mode, nghttp2_hd_map *map,
1211
0
                                     uint32_t hash) {
1212
0
  search_result res = {-1, 0};
1213
0
  const nghttp2_hd_entry *ent;
1214
0
  int exact_match;
1215
0
  int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING;
1216
1217
0
  exact_match = 0;
1218
0
  ent = hd_map_find(map, &exact_match, nv, token, hash, name_only);
1219
1220
0
  if (!exact_match && token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1221
0
    return search_static_table(nv, token, name_only);
1222
0
  }
1223
1224
0
  if (ent == NULL) {
1225
0
    return res;
1226
0
  }
1227
1228
0
  res.index = (nghttp2_ssize)(context->next_seq - 1 - ent->seq +
1229
0
                              NGHTTP2_STATIC_TABLE_LENGTH);
1230
0
  res.name_value_match = exact_match;
1231
1232
0
  return res;
1233
0
}
1234
1235
static void hd_context_shrink_table_size(nghttp2_hd_context *context,
1236
5.31k
                                         nghttp2_hd_map *map) {
1237
5.31k
  nghttp2_mem *mem;
1238
1239
5.31k
  mem = context->mem;
1240
1241
6.03k
  while (context->hd_table_bufsize > context->hd_table_bufsize_max &&
1242
714
         context->hd_table.len > 0) {
1243
714
    size_t idx = context->hd_table.len - 1;
1244
714
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1245
714
    context->hd_table_bufsize -=
1246
714
      entry_room(ent->nv.name->len, ent->nv.value->len);
1247
714
    hd_ringbuf_pop_back(&context->hd_table);
1248
714
    if (map) {
1249
0
      hd_map_remove(map, ent);
1250
0
    }
1251
1252
714
    nghttp2_hd_entry_free(ent);
1253
714
    nghttp2_mem_free(mem, ent);
1254
714
  }
1255
5.31k
}
1256
1257
int nghttp2_hd_deflate_change_table_size(
1258
2.04k
  nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
1259
2.04k
  size_t next_bufsize = nghttp2_min_size(
1260
2.04k
    settings_max_dynamic_table_size, deflater->deflate_hd_table_bufsize_max);
1261
1262
2.04k
  deflater->ctx.hd_table_bufsize_max = next_bufsize;
1263
1264
2.04k
  deflater->min_hd_table_bufsize_max =
1265
2.04k
    nghttp2_min_size(deflater->min_hd_table_bufsize_max, next_bufsize);
1266
1267
2.04k
  deflater->notify_table_size_change = 1;
1268
1269
2.04k
  hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
1270
2.04k
  return 0;
1271
2.04k
}
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
147k
static size_t get_max_index(nghttp2_hd_context *context) {
1310
147k
  return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH;
1311
147k
}
1312
1313
146k
nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
1314
146k
  assert(INDEX_RANGE_VALID(context, idx));
1315
146k
  if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1316
36.7k
    return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
1317
36.7k
      ->nv;
1318
110k
  } else {
1319
110k
    const nghttp2_hd_static_entry *ent = &static_table[idx];
1320
110k
    nghttp2_hd_nv nv = {(nghttp2_rcbuf *)&ent->name,
1321
110k
                        (nghttp2_rcbuf *)&ent->value, ent->token,
1322
110k
                        NGHTTP2_NV_FLAG_NONE};
1323
110k
    return nv;
1324
110k
  }
1325
146k
}
1326
1327
static const nghttp2_nv *nghttp2_hd_table_get2(nghttp2_hd_context *context,
1328
0
                                               size_t idx) {
1329
0
  assert(INDEX_RANGE_VALID(context, idx));
1330
0
  if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1331
0
    return &hd_ringbuf_get(&context->hd_table,
1332
0
                           idx - NGHTTP2_STATIC_TABLE_LENGTH)
1333
0
              ->cnv;
1334
0
  }
1335
1336
0
  return &static_table[idx].cnv;
1337
0
}
1338
1339
static int hd_deflate_decide_indexing(nghttp2_hd_deflater *deflater,
1340
0
                                      const nghttp2_nv *nv, int32_t token) {
1341
0
  if (token == NGHTTP2_TOKEN__PATH || token == NGHTTP2_TOKEN_AGE ||
1342
0
      token == NGHTTP2_TOKEN_CONTENT_LENGTH || token == NGHTTP2_TOKEN_ETAG ||
1343
0
      token == NGHTTP2_TOKEN_IF_MODIFIED_SINCE ||
1344
0
      token == NGHTTP2_TOKEN_IF_NONE_MATCH || token == NGHTTP2_TOKEN_LOCATION ||
1345
0
      token == NGHTTP2_TOKEN_SET_COOKIE ||
1346
0
      entry_room(nv->namelen, nv->valuelen) >
1347
0
        deflater->ctx.hd_table_bufsize_max * 3 / 4) {
1348
0
    return NGHTTP2_HD_WITHOUT_INDEXING;
1349
0
  }
1350
1351
0
  return NGHTTP2_HD_WITH_INDEXING;
1352
0
}
1353
1354
static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
1355
0
                      const nghttp2_nv *nv) {
1356
0
  int rv;
1357
0
  search_result res;
1358
0
  nghttp2_ssize idx;
1359
0
  int indexing_mode;
1360
0
  int32_t token;
1361
0
  nghttp2_mem *mem;
1362
0
  uint32_t hash = 0;
1363
1364
0
  DEBUGF("deflatehd: deflating %.*s: %.*s\n", (int)nv->namelen, nv->name,
1365
0
         (int)nv->valuelen, nv->value);
1366
1367
0
  mem = deflater->ctx.mem;
1368
1369
0
  token = lookup_token(nv->name, nv->namelen);
1370
0
  if (token == -1) {
1371
0
    hash = name_hash(nv);
1372
0
  } else if (token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1373
0
    hash = static_table[token].hash;
1374
0
  }
1375
1376
  /* Don't index authorization header field since it may contain low
1377
     entropy secret data (e.g., id/password).  Also cookie header
1378
     field with less than 20 bytes value is also never indexed.  This
1379
     is the same criteria used in Firefox codebase. */
1380
0
  indexing_mode = token == NGHTTP2_TOKEN_AUTHORIZATION ||
1381
0
                      (token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) ||
1382
0
                      (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX)
1383
0
                    ? NGHTTP2_HD_NEVER_INDEXING
1384
0
                    : hd_deflate_decide_indexing(deflater, nv, token);
1385
1386
0
  res = search_hd_table(&deflater->ctx, nv, token, indexing_mode,
1387
0
                        &deflater->map, hash);
1388
1389
0
  idx = res.index;
1390
1391
0
  if (res.name_value_match) {
1392
0
    DEBUGF("deflatehd: name/value match index=%td\n", idx);
1393
1394
0
    rv = emit_indexed_block(bufs, (size_t)idx);
1395
0
    if (rv != 0) {
1396
0
      return rv;
1397
0
    }
1398
1399
0
    return 0;
1400
0
  }
1401
1402
0
  if (res.index != -1) {
1403
0
    DEBUGF("deflatehd: name match index=%td\n", res.index);
1404
0
  }
1405
1406
0
  if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1407
0
    nghttp2_hd_nv hd_nv;
1408
1409
0
    if (idx != -1) {
1410
0
      hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name;
1411
0
      nghttp2_rcbuf_incref(hd_nv.name);
1412
0
    } else {
1413
0
      rv = nghttp2_rcbuf_new2(&hd_nv.name, nv->name, nv->namelen, mem);
1414
0
      if (rv != 0) {
1415
0
        return rv;
1416
0
      }
1417
0
    }
1418
1419
0
    rv = nghttp2_rcbuf_new2(&hd_nv.value, nv->value, nv->valuelen, mem);
1420
1421
0
    if (rv != 0) {
1422
0
      nghttp2_rcbuf_decref(hd_nv.name);
1423
0
      return rv;
1424
0
    }
1425
1426
0
    hd_nv.token = token;
1427
0
    hd_nv.flags = NGHTTP2_NV_FLAG_NONE;
1428
1429
0
    rv = add_hd_table_incremental(&deflater->ctx, &hd_nv, &deflater->map, hash);
1430
1431
0
    nghttp2_rcbuf_decref(hd_nv.value);
1432
0
    nghttp2_rcbuf_decref(hd_nv.name);
1433
1434
0
    if (rv != 0) {
1435
0
      return NGHTTP2_ERR_HEADER_COMP;
1436
0
    }
1437
0
  }
1438
0
  if (idx == -1) {
1439
0
    rv = emit_newname_block(bufs, nv, indexing_mode);
1440
0
  } else {
1441
0
    rv = emit_indname_block(bufs, (size_t)idx, nv, indexing_mode);
1442
0
  }
1443
0
  if (rv != 0) {
1444
0
    return rv;
1445
0
  }
1446
1447
0
  return 0;
1448
0
}
1449
1450
int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
1451
                               nghttp2_bufs *bufs, const nghttp2_nv *nv,
1452
0
                               size_t nvlen) {
1453
0
  size_t i;
1454
0
  int rv = 0;
1455
1456
0
  if (deflater->ctx.bad) {
1457
0
    return NGHTTP2_ERR_HEADER_COMP;
1458
0
  }
1459
1460
0
  if (deflater->notify_table_size_change) {
1461
0
    size_t min_hd_table_bufsize_max;
1462
1463
0
    min_hd_table_bufsize_max = deflater->min_hd_table_bufsize_max;
1464
1465
0
    deflater->notify_table_size_change = 0;
1466
0
    deflater->min_hd_table_bufsize_max = UINT32_MAX;
1467
1468
0
    if (deflater->ctx.hd_table_bufsize_max > min_hd_table_bufsize_max) {
1469
0
      rv = emit_table_size(bufs, min_hd_table_bufsize_max);
1470
1471
0
      if (rv != 0) {
1472
0
        goto fail;
1473
0
      }
1474
0
    }
1475
1476
0
    rv = emit_table_size(bufs, deflater->ctx.hd_table_bufsize_max);
1477
1478
0
    if (rv != 0) {
1479
0
      goto fail;
1480
0
    }
1481
0
  }
1482
1483
0
  for (i = 0; i < nvlen; ++i) {
1484
0
    rv = deflate_nv(deflater, bufs, &nv[i]);
1485
0
    if (rv != 0) {
1486
0
      goto fail;
1487
0
    }
1488
0
  }
1489
1490
0
  DEBUGF("deflatehd: all input name/value pairs were deflated\n");
1491
1492
0
  return 0;
1493
0
fail:
1494
0
  DEBUGF("deflatehd: error return %d\n", rv);
1495
1496
0
  deflater->ctx.bad = 1;
1497
0
  return rv;
1498
0
}
1499
1500
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
1501
                              size_t buflen, const nghttp2_nv *nv,
1502
0
                              size_t nvlen) {
1503
0
  return (ssize_t)nghttp2_hd_deflate_hd2(deflater, buf, buflen, nv, nvlen);
1504
0
}
1505
1506
nghttp2_ssize nghttp2_hd_deflate_hd2(nghttp2_hd_deflater *deflater,
1507
                                     uint8_t *buf, size_t buflen,
1508
0
                                     const nghttp2_nv *nv, size_t nvlen) {
1509
0
  nghttp2_bufs bufs;
1510
0
  int rv;
1511
0
  nghttp2_mem *mem;
1512
1513
0
  mem = deflater->ctx.mem;
1514
1515
0
  rv = nghttp2_bufs_wrap_init(&bufs, buf, buflen, mem);
1516
1517
0
  if (rv != 0) {
1518
0
    return rv;
1519
0
  }
1520
1521
0
  rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nv, nvlen);
1522
1523
0
  buflen = nghttp2_bufs_len(&bufs);
1524
1525
0
  nghttp2_bufs_wrap_free(&bufs);
1526
1527
0
  if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
1528
0
    return NGHTTP2_ERR_INSUFF_BUFSIZE;
1529
0
  }
1530
1531
0
  if (rv != 0) {
1532
0
    return rv;
1533
0
  }
1534
1535
0
  return (nghttp2_ssize)buflen;
1536
0
}
1537
1538
ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
1539
                                  const nghttp2_vec *vec, size_t veclen,
1540
0
                                  const nghttp2_nv *nv, size_t nvlen) {
1541
0
  return (ssize_t)nghttp2_hd_deflate_hd_vec2(deflater, vec, veclen, nv, nvlen);
1542
0
}
1543
1544
nghttp2_ssize nghttp2_hd_deflate_hd_vec2(nghttp2_hd_deflater *deflater,
1545
                                         const nghttp2_vec *vec, size_t veclen,
1546
0
                                         const nghttp2_nv *nv, size_t nvlen) {
1547
0
  nghttp2_bufs bufs;
1548
0
  int rv;
1549
0
  nghttp2_mem *mem;
1550
0
  size_t buflen;
1551
1552
0
  mem = deflater->ctx.mem;
1553
1554
0
  rv = nghttp2_bufs_wrap_init2(&bufs, vec, veclen, mem);
1555
1556
0
  if (rv != 0) {
1557
0
    return rv;
1558
0
  }
1559
1560
0
  rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nv, nvlen);
1561
1562
0
  buflen = nghttp2_bufs_len(&bufs);
1563
1564
0
  nghttp2_bufs_wrap_free(&bufs);
1565
1566
0
  if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
1567
0
    return NGHTTP2_ERR_INSUFF_BUFSIZE;
1568
0
  }
1569
1570
0
  if (rv != 0) {
1571
0
    return rv;
1572
0
  }
1573
1574
0
  return (nghttp2_ssize)buflen;
1575
0
}
1576
1577
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
1578
0
                                const nghttp2_nv *nva, size_t nvlen) {
1579
0
  size_t n = 0;
1580
0
  size_t i;
1581
0
  (void)deflater;
1582
1583
  /* Possible Maximum Header Table Size Change.  Encoding (1u << 31) -
1584
     1 using 4 bit prefix requires 6 bytes.  We may emit this at most
1585
     twice. */
1586
0
  n += 12;
1587
1588
  /* Use Literal Header Field without indexing - New Name, since it is
1589
     most space consuming format.  Also we choose the less one between
1590
     non-huffman and huffman, so using literal byte count is
1591
     sufficient for upper bound.
1592
1593
     Encoding (1u << 31) - 1 using 7 bit prefix requires 6 bytes.  We
1594
     need 2 of this for |nvlen| header fields. */
1595
0
  n += 6 * 2 * nvlen;
1596
1597
0
  for (i = 0; i < nvlen; ++i) {
1598
0
    n += nva[i].namelen + nva[i].valuelen;
1599
0
  }
1600
1601
0
  return n;
1602
0
}
1603
1604
int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
1605
0
                           size_t deflate_hd_table_bufsize_max) {
1606
0
  return nghttp2_hd_deflate_new2(deflater_ptr, deflate_hd_table_bufsize_max,
1607
0
                                 NULL);
1608
0
}
1609
1610
int nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr,
1611
                            size_t deflate_hd_table_bufsize_max,
1612
0
                            nghttp2_mem *mem) {
1613
0
  int rv;
1614
0
  nghttp2_hd_deflater *deflater;
1615
1616
0
  if (mem == NULL) {
1617
0
    mem = nghttp2_mem_default();
1618
0
  }
1619
1620
0
  deflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_deflater));
1621
1622
0
  if (deflater == NULL) {
1623
0
    return NGHTTP2_ERR_NOMEM;
1624
0
  }
1625
1626
0
  rv = nghttp2_hd_deflate_init2(deflater, deflate_hd_table_bufsize_max, mem);
1627
1628
0
  if (rv != 0) {
1629
0
    nghttp2_mem_free(mem, deflater);
1630
1631
0
    return rv;
1632
0
  }
1633
1634
0
  *deflater_ptr = deflater;
1635
1636
0
  return 0;
1637
0
}
1638
1639
0
void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater) {
1640
0
  nghttp2_mem *mem;
1641
1642
0
  mem = deflater->ctx.mem;
1643
1644
0
  nghttp2_hd_deflate_free(deflater);
1645
1646
0
  nghttp2_mem_free(mem, deflater);
1647
0
}
1648
1649
static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater,
1650
223k
                                           const uint8_t *in) {
1651
223k
  inflater->huffman_encoded = (*in & (1 << 7)) != 0;
1652
223k
}
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
375k
                                         size_t maxlen) {
1671
375k
  nghttp2_ssize rv;
1672
375k
  uint32_t out;
1673
1674
375k
  *rfin = 0;
1675
1676
375k
  rv = decode_length(&out, &inflater->shift, rfin, (uint32_t)inflater->left,
1677
375k
                     inflater->shift, in, last, prefix);
1678
1679
375k
  if (rv == -1) {
1680
113
    DEBUGF("inflatehd: integer decoding failed\n");
1681
113
    return NGHTTP2_ERR_HEADER_COMP;
1682
113
  }
1683
1684
375k
  if (out > maxlen) {
1685
725
    DEBUGF("inflatehd: integer exceeded the maximum value %zu\n", maxlen);
1686
725
    return NGHTTP2_ERR_HEADER_COMP;
1687
725
  }
1688
1689
374k
  inflater->left = out;
1690
1691
374k
  DEBUGF("inflatehd: decoded integer is %u\n", out);
1692
1693
374k
  return rv;
1694
375k
}
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
21.1k
                                          const uint8_t *last) {
1712
21.1k
  nghttp2_ssize readlen;
1713
21.1k
  int fin = 0;
1714
21.1k
  if ((size_t)(last - in) >= inflater->left) {
1715
21.0k
    last = in + inflater->left;
1716
21.0k
    fin = 1;
1717
21.0k
  }
1718
21.1k
  readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
1719
21.1k
                                   (size_t)(last - in), fin);
1720
1721
21.1k
  if (readlen < 0) {
1722
22
    DEBUGF("inflatehd: huffman decoding failed\n");
1723
22
    return readlen;
1724
22
  }
1725
21.1k
  if (nghttp2_hd_huff_decode_failure_state(&inflater->huff_decode_ctx)) {
1726
11
    DEBUGF("inflatehd: huffman decoding failed\n");
1727
11
    return NGHTTP2_ERR_HEADER_COMP;
1728
11
  }
1729
1730
21.1k
  inflater->left -= (size_t)readlen;
1731
21.1k
  return readlen;
1732
21.1k
}
1733
1734
/*
1735
 * Reads |inflater->left| bytes from the range [in, last) and copies
1736
 * them into the |buffer|.
1737
 *
1738
 * This function returns the number of bytes read if it succeeds, or
1739
 * one of the following negative error codes:
1740
 *
1741
 * NGHTTP2_ERR_NOMEM
1742
 *   Out of memory
1743
 * NGHTTP2_ERR_HEADER_COMP
1744
 *   Header decompression failed
1745
 */
1746
static nghttp2_ssize hd_inflate_read(nghttp2_hd_inflater *inflater,
1747
                                     nghttp2_buf *buf, const uint8_t *in,
1748
201k
                                     const uint8_t *last) {
1749
201k
  size_t len = nghttp2_min_size((size_t)(last - in), inflater->left);
1750
1751
201k
  buf->last = nghttp2_cpymem(buf->last, in, len);
1752
1753
201k
  inflater->left -= len;
1754
201k
  return (nghttp2_ssize)len;
1755
201k
}
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
112k
                                      nghttp2_hd_nv *nv_out) {
1763
112k
  nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1764
1765
112k
  emit_header(nv_out, &nv);
1766
112k
}
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
94.0k
                                     nghttp2_hd_nv *nv_out) {
1781
94.0k
  nghttp2_hd_nv nv;
1782
94.0k
  int rv;
1783
1784
94.0k
  if (inflater->no_index) {
1785
3.73k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1786
90.3k
  } else {
1787
90.3k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1788
90.3k
  }
1789
1790
94.0k
  nv.name = inflater->namercbuf;
1791
94.0k
  nv.value = inflater->valuercbuf;
1792
94.0k
  nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len);
1793
1794
94.0k
  if (inflater->index_required) {
1795
9.91k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1796
1797
9.91k
    if (rv != 0) {
1798
0
      return rv;
1799
0
    }
1800
9.91k
  }
1801
1802
94.0k
  emit_header(nv_out, &nv);
1803
1804
94.0k
  inflater->nv_name_keep = nv.name;
1805
94.0k
  inflater->nv_value_keep = nv.value;
1806
1807
94.0k
  inflater->namercbuf = NULL;
1808
94.0k
  inflater->valuercbuf = NULL;
1809
1810
94.0k
  return 0;
1811
94.0k
}
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
34.4k
                                     nghttp2_hd_nv *nv_out) {
1826
34.4k
  nghttp2_hd_nv nv;
1827
34.4k
  int rv;
1828
1829
34.4k
  nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1830
1831
34.4k
  if (inflater->no_index) {
1832
3.44k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1833
30.9k
  } else {
1834
30.9k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1835
30.9k
  }
1836
1837
34.4k
  nghttp2_rcbuf_incref(nv.name);
1838
1839
34.4k
  nv.value = inflater->valuercbuf;
1840
1841
34.4k
  if (inflater->index_required) {
1842
18.8k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1843
18.8k
    if (rv != 0) {
1844
0
      nghttp2_rcbuf_decref(nv.name);
1845
0
      return NGHTTP2_ERR_NOMEM;
1846
0
    }
1847
18.8k
  }
1848
1849
34.4k
  emit_header(nv_out, &nv);
1850
1851
34.4k
  inflater->nv_name_keep = nv.name;
1852
34.4k
  inflater->nv_value_keep = nv.value;
1853
1854
34.4k
  inflater->valuercbuf = NULL;
1855
1856
34.4k
  return 0;
1857
34.4k
}
1858
1859
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
1860
                              int *inflate_flags, uint8_t *in, size_t inlen,
1861
0
                              int in_final) {
1862
0
  return nghttp2_hd_inflate_hd2(inflater, nv_out, inflate_flags, in, inlen,
1863
0
                                in_final);
1864
0
}
1865
1866
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
1867
                               nghttp2_nv *nv_out, int *inflate_flags,
1868
0
                               const uint8_t *in, size_t inlen, int in_final) {
1869
0
  return (nghttp2_ssize)nghttp2_hd_inflate_hd3(inflater, nv_out, inflate_flags,
1870
0
                                               in, inlen, in_final);
1871
0
}
1872
1873
nghttp2_ssize nghttp2_hd_inflate_hd3(nghttp2_hd_inflater *inflater,
1874
                                     nghttp2_nv *nv_out, int *inflate_flags,
1875
                                     const uint8_t *in, size_t inlen,
1876
0
                                     int in_final) {
1877
0
  nghttp2_ssize rv;
1878
0
  nghttp2_hd_nv hd_nv;
1879
1880
0
  rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
1881
0
                                in_final);
1882
1883
0
  if (rv < 0) {
1884
0
    return rv;
1885
0
  }
1886
1887
0
  if (*inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
1888
0
    nv_out->name = hd_nv.name->base;
1889
0
    nv_out->namelen = hd_nv.name->len;
1890
1891
0
    nv_out->value = hd_nv.value->base;
1892
0
    nv_out->valuelen = hd_nv.value->len;
1893
1894
0
    nv_out->flags = hd_nv.flags;
1895
0
  }
1896
1897
0
  return rv;
1898
0
}
1899
1900
nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
1901
                                       nghttp2_hd_nv *nv_out,
1902
                                       int *inflate_flags, const uint8_t *in,
1903
270k
                                       size_t inlen, int in_final) {
1904
270k
  nghttp2_ssize rv = 0;
1905
270k
  const uint8_t *first = in;
1906
270k
  const uint8_t *last = in + inlen;
1907
270k
  int rfin = 0;
1908
270k
  int busy = 0;
1909
270k
  nghttp2_mem *mem;
1910
1911
270k
  mem = inflater->ctx.mem;
1912
1913
270k
  if (inflater->ctx.bad) {
1914
0
    return NGHTTP2_ERR_HEADER_COMP;
1915
0
  }
1916
1917
270k
  DEBUGF("inflatehd: start state=%d\n", inflater->state);
1918
270k
  hd_inflate_keep_free(inflater);
1919
270k
  *inflate_flags = NGHTTP2_HD_INFLATE_NONE;
1920
871k
  for (; in != last || busy;) {
1921
844k
    busy = 0;
1922
844k
    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
21.2k
    case NGHTTP2_HD_STATE_INFLATE_START:
1933
245k
    case NGHTTP2_HD_STATE_OPCODE:
1934
245k
      if ((*in & 0xe0u) == 0x20u) {
1935
3.40k
        DEBUGF("inflatehd: header table size change\n");
1936
3.40k
        if (inflater->state == NGHTTP2_HD_STATE_OPCODE) {
1937
26
          DEBUGF("inflatehd: header table size change must appear at the head "
1938
26
                 "of header block\n");
1939
26
          rv = NGHTTP2_ERR_HEADER_COMP;
1940
26
          goto fail;
1941
26
        }
1942
3.37k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1943
3.37k
        inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
1944
242k
      } else if (*in & 0x80u) {
1945
112k
        DEBUGF("inflatehd: indexed repr\n");
1946
112k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1947
112k
        inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1948
129k
      } else {
1949
129k
        if (*in == 0x40u || *in == 0 || *in == 0x10u) {
1950
94.6k
          DEBUGF("inflatehd: literal header repr - new name\n");
1951
94.6k
          inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
1952
94.6k
          inflater->state = NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN;
1953
94.6k
        } else {
1954
35.0k
          DEBUGF("inflatehd: literal header repr - indexed name\n");
1955
35.0k
          inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
1956
35.0k
          inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1957
35.0k
        }
1958
129k
        inflater->index_required = (*in & 0x40) != 0;
1959
129k
        inflater->no_index = (*in & 0xf0u) == 0x10u;
1960
129k
        DEBUGF("inflatehd: indexing required=%d, no_index=%d\n",
1961
129k
               inflater->index_required, inflater->no_index);
1962
129k
        if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1963
94.6k
          ++in;
1964
94.6k
        }
1965
129k
      }
1966
245k
      inflater->left = 0;
1967
245k
      inflater->shift = 0;
1968
245k
      break;
1969
3.93k
    case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
1970
3.93k
      rfin = 0;
1971
3.93k
      rv = hd_inflate_read_len(
1972
3.93k
        inflater, &rfin, in, last, 5,
1973
3.93k
        nghttp2_min_size(inflater->min_hd_table_bufsize_max,
1974
3.93k
                         inflater->settings_hd_table_bufsize_max));
1975
3.93k
      if (rv < 0) {
1976
163
        goto fail;
1977
163
      }
1978
3.76k
      in += rv;
1979
3.76k
      if (!rfin) {
1980
589
        goto almost_ok;
1981
589
      }
1982
3.18k
      DEBUGF("inflatehd: table_size=%zu\n", inflater->left);
1983
3.18k
      inflater->min_hd_table_bufsize_max = UINT32_MAX;
1984
3.18k
      inflater->ctx.hd_table_bufsize_max = inflater->left;
1985
3.18k
      hd_context_shrink_table_size(&inflater->ctx, NULL);
1986
3.18k
      inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
1987
3.18k
      break;
1988
147k
    case NGHTTP2_HD_STATE_READ_INDEX: {
1989
147k
      size_t prefixlen;
1990
1991
147k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
1992
112k
        prefixlen = 7;
1993
112k
      } else if (inflater->index_required) {
1994
19.1k
        prefixlen = 6;
1995
19.1k
      } else {
1996
16.0k
        prefixlen = 4;
1997
16.0k
      }
1998
1999
147k
      rfin = 0;
2000
147k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
2001
147k
                               get_max_index(&inflater->ctx));
2002
147k
      if (rv < 0) {
2003
346
        goto fail;
2004
346
      }
2005
2006
147k
      in += rv;
2007
2008
147k
      if (!rfin) {
2009
137
        goto almost_ok;
2010
137
      }
2011
2012
147k
      if (inflater->left == 0) {
2013
6
        rv = NGHTTP2_ERR_HEADER_COMP;
2014
6
        goto fail;
2015
6
      }
2016
2017
147k
      DEBUGF("inflatehd: index=%zu\n", inflater->left);
2018
147k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
2019
112k
        inflater->index = inflater->left;
2020
112k
        --inflater->index;
2021
2022
112k
        hd_inflate_commit_indexed(inflater, nv_out);
2023
2024
112k
        inflater->state = NGHTTP2_HD_STATE_OPCODE;
2025
112k
        *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2026
112k
        return (nghttp2_ssize)(in - first);
2027
112k
      } else {
2028
34.8k
        inflater->index = inflater->left;
2029
34.8k
        --inflater->index;
2030
2031
34.8k
        inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2032
34.8k
      }
2033
34.8k
      break;
2034
147k
    }
2035
94.5k
    case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
2036
94.5k
      hd_inflate_set_huffman_encoded(inflater, in);
2037
94.5k
      inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
2038
94.5k
      inflater->left = 0;
2039
94.5k
      inflater->shift = 0;
2040
94.5k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2041
    /* Fall through */
2042
94.6k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN:
2043
94.6k
      rfin = 0;
2044
94.6k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2045
94.6k
      if (rv < 0) {
2046
149
        goto fail;
2047
149
      }
2048
94.5k
      in += rv;
2049
94.5k
      if (!rfin) {
2050
166
        DEBUGF("inflatehd: integer not fully decoded. current=%zu\n",
2051
166
               inflater->left);
2052
2053
166
        goto almost_ok;
2054
166
      }
2055
2056
94.3k
      if (inflater->huffman_encoded) {
2057
6.83k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2058
2059
6.83k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
2060
2061
6.83k
        rv =
2062
6.83k
          nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1, mem);
2063
87.5k
      } else {
2064
87.5k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
2065
87.5k
        rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
2066
87.5k
      }
2067
2068
94.3k
      if (rv != 0) {
2069
0
        goto fail;
2070
0
      }
2071
2072
94.3k
      nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base,
2073
94.3k
                            inflater->namercbuf->len);
2074
2075
94.3k
      break;
2076
6.81k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
2077
6.81k
      rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
2078
6.81k
      if (rv < 0) {
2079
15
        goto fail;
2080
15
      }
2081
2082
6.80k
      in += rv;
2083
2084
6.80k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2085
2086
6.80k
      if (inflater->left) {
2087
55
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2088
2089
55
        goto almost_ok;
2090
55
      }
2091
2092
6.74k
      *inflater->namebuf.last = '\0';
2093
6.74k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2094
2095
6.74k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2096
2097
6.74k
      break;
2098
87.4k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
2099
87.4k
      rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
2100
87.4k
      if (rv < 0) {
2101
0
        goto fail;
2102
0
      }
2103
2104
87.4k
      in += rv;
2105
2106
87.4k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2107
87.4k
      if (inflater->left) {
2108
99
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2109
2110
99
        goto almost_ok;
2111
99
      }
2112
2113
87.3k
      *inflater->namebuf.last = '\0';
2114
87.3k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2115
2116
87.3k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2117
2118
87.3k
      break;
2119
128k
    case NGHTTP2_HD_STATE_CHECK_VALUELEN:
2120
128k
      hd_inflate_set_huffman_encoded(inflater, in);
2121
128k
      inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
2122
128k
      inflater->left = 0;
2123
128k
      inflater->shift = 0;
2124
128k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2125
    /* Fall through */
2126
129k
    case NGHTTP2_HD_STATE_READ_VALUELEN:
2127
129k
      rfin = 0;
2128
129k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2129
129k
      if (rv < 0) {
2130
180
        goto fail;
2131
180
      }
2132
2133
128k
      in += rv;
2134
2135
128k
      if (!rfin) {
2136
209
        goto almost_ok;
2137
209
      }
2138
2139
128k
      DEBUGF("inflatehd: valuelen=%zu\n", inflater->left);
2140
2141
128k
      if (inflater->huffman_encoded) {
2142
14.3k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2143
2144
14.3k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
2145
2146
14.3k
        rv =
2147
14.3k
          nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1, mem);
2148
114k
      } else {
2149
114k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
2150
2151
114k
        rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem);
2152
114k
      }
2153
2154
128k
      if (rv != 0) {
2155
0
        goto fail;
2156
0
      }
2157
2158
128k
      nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base,
2159
128k
                            inflater->valuercbuf->len);
2160
2161
128k
      busy = 1;
2162
2163
128k
      break;
2164
14.3k
    case NGHTTP2_HD_STATE_READ_VALUEHUFF:
2165
14.3k
      rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
2166
14.3k
      if (rv < 0) {
2167
18
        goto fail;
2168
18
      }
2169
2170
14.3k
      in += rv;
2171
2172
14.3k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2173
2174
14.3k
      if (inflater->left) {
2175
88
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2176
2177
88
        goto almost_ok;
2178
88
      }
2179
2180
14.2k
      *inflater->valuebuf.last = '\0';
2181
14.2k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2182
2183
14.2k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2184
6.26k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2185
7.99k
      } else {
2186
7.99k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2187
7.99k
      }
2188
2189
14.2k
      if (rv != 0) {
2190
0
        goto fail;
2191
0
      }
2192
2193
14.2k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2194
14.2k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2195
2196
14.2k
      return (nghttp2_ssize)(in - first);
2197
114k
    case NGHTTP2_HD_STATE_READ_VALUE:
2198
114k
      rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
2199
114k
      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
114k
      in += rv;
2206
2207
114k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2208
2209
114k
      if (inflater->left) {
2210
150
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2211
150
        goto almost_ok;
2212
150
      }
2213
2214
114k
      *inflater->valuebuf.last = '\0';
2215
114k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2216
2217
114k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2218
87.7k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2219
87.7k
      } else {
2220
26.4k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2221
26.4k
      }
2222
2223
114k
      if (rv != 0) {
2224
0
        goto fail;
2225
0
      }
2226
2227
114k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2228
114k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2229
2230
114k
      return (nghttp2_ssize)(in - first);
2231
844k
    }
2232
844k
  }
2233
2234
270k
  assert(in == last);
2235
2236
26.6k
  DEBUGF("inflatehd: all input bytes were processed\n");
2237
2238
26.6k
  if (in_final) {
2239
19.9k
    DEBUGF("inflatehd: in_final set\n");
2240
2241
19.9k
    if (inflater->state != NGHTTP2_HD_STATE_OPCODE &&
2242
10.4k
        inflater->state != NGHTTP2_HD_STATE_INFLATE_START) {
2243
12
      DEBUGF("inflatehd: unacceptable state=%d\n", inflater->state);
2244
12
      rv = NGHTTP2_ERR_HEADER_COMP;
2245
2246
12
      goto fail;
2247
12
    }
2248
19.9k
    *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
2249
19.9k
  }
2250
26.6k
  return (nghttp2_ssize)(in - first);
2251
2252
1.49k
almost_ok:
2253
1.49k
  if (in_final) {
2254
8
    DEBUGF("inflatehd: input ended prematurely\n");
2255
2256
8
    rv = NGHTTP2_ERR_HEADER_COMP;
2257
2258
8
    goto fail;
2259
8
  }
2260
1.48k
  return (nghttp2_ssize)(in - first);
2261
2262
926
fail:
2263
926
  DEBUGF("inflatehd: error return %td\n", rv);
2264
2265
926
  inflater->ctx.bad = 1;
2266
926
  return rv;
2267
1.49k
}
2268
2269
19.9k
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
2270
19.9k
  hd_inflate_keep_free(inflater);
2271
19.9k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
2272
19.9k
  return 0;
2273
19.9k
}
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
}