Coverage Report

Created: 2025-10-13 06:27

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