Coverage Report

Created: 2026-09-14 06:50

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