Coverage Report

Created: 2026-08-13 06:26

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
75.0k
static int memeq(const void *s1, const void *s2, size_t n) {
130
75.0k
  return memcmp(s1, s2, n) == 0;
131
75.0k
}
132
133
/*
134
 * This function was generated by genlibtokenlookup.py.  Inspired by
135
 * h2o header lookup.  https://github.com/h2o/h2o
136
 */
137
110k
static int32_t lookup_token(const uint8_t *name, size_t namelen) {
138
110k
  switch (namelen) {
139
1.04k
  case 2:
140
1.04k
    switch (name[1]) {
141
775
    case 'e':
142
775
      if (memeq("t", name, 1)) {
143
481
        return NGHTTP2_TOKEN_TE;
144
481
      }
145
294
      break;
146
1.04k
    }
147
562
    break;
148
1.21k
  case 3:
149
1.21k
    switch (name[2]) {
150
443
    case 'a':
151
443
      if (memeq("vi", name, 2)) {
152
195
        return NGHTTP2_TOKEN_VIA;
153
195
      }
154
248
      break;
155
420
    case 'e':
156
420
      if (memeq("ag", name, 2)) {
157
194
        return NGHTTP2_TOKEN_AGE;
158
194
      }
159
226
      break;
160
1.21k
    }
161
828
    break;
162
6.70k
  case 4:
163
6.70k
    switch (name[3]) {
164
950
    case 'e':
165
950
      if (memeq("dat", name, 3)) {
166
686
        return NGHTTP2_TOKEN_DATE;
167
686
      }
168
264
      break;
169
713
    case 'g':
170
713
      if (memeq("eta", name, 3)) {
171
401
        return NGHTTP2_TOKEN_ETAG;
172
401
      }
173
312
      break;
174
545
    case 'k':
175
545
      if (memeq("lin", name, 3)) {
176
307
        return NGHTTP2_TOKEN_LINK;
177
307
      }
178
238
      break;
179
444
    case 'm':
180
444
      if (memeq("fro", name, 3)) {
181
200
        return NGHTTP2_TOKEN_FROM;
182
200
      }
183
244
      break;
184
536
    case 't':
185
536
      if (memeq("hos", name, 3)) {
186
197
        return NGHTTP2_TOKEN_HOST;
187
197
      }
188
339
      break;
189
1.88k
    case 'y':
190
1.88k
      if (memeq("var", name, 3)) {
191
593
        return NGHTTP2_TOKEN_VARY;
192
593
      }
193
1.28k
      break;
194
6.70k
    }
195
4.32k
    break;
196
4.32k
  case 5:
197
2.95k
    switch (name[4]) {
198
1.54k
    case 'e':
199
1.54k
      if (memeq("rang", name, 4)) {
200
1.02k
        return NGHTTP2_TOKEN_RANGE;
201
1.02k
      }
202
520
      break;
203
520
    case 'h':
204
466
      if (memeq(":pat", name, 4)) {
205
244
        return NGHTTP2_TOKEN__PATH;
206
244
      }
207
222
      break;
208
392
    case 'w':
209
392
      if (memeq("allo", name, 4)) {
210
197
        return NGHTTP2_TOKEN_ALLOW;
211
197
      }
212
195
      break;
213
2.95k
    }
214
1.48k
    break;
215
3.45k
  case 6:
216
3.45k
    switch (name[5]) {
217
749
    case 'e':
218
749
      if (memeq("cooki", name, 5)) {
219
194
        return NGHTTP2_TOKEN_COOKIE;
220
194
      }
221
555
      break;
222
555
    case 'r':
223
396
      if (memeq("serve", name, 5)) {
224
194
        return NGHTTP2_TOKEN_SERVER;
225
194
      }
226
202
      break;
227
851
    case 't':
228
851
      if (memeq("accep", name, 5)) {
229
321
        return NGHTTP2_TOKEN_ACCEPT;
230
321
      }
231
530
      if (memeq("expec", name, 5)) {
232
320
        return NGHTTP2_TOKEN_EXPECT;
233
320
      }
234
210
      break;
235
3.45k
    }
236
2.42k
    break;
237
18.5k
  case 7:
238
18.5k
    switch (name[6]) {
239
438
    case 'd':
240
438
      if (memeq(":metho", name, 6)) {
241
216
        return NGHTTP2_TOKEN__METHOD;
242
216
      }
243
222
      break;
244
1.02k
    case 'e':
245
1.02k
      if (memeq(":schem", name, 6)) {
246
222
        return NGHTTP2_TOKEN__SCHEME;
247
222
      }
248
803
      if (memeq("upgrad", name, 6)) {
249
368
        return NGHTTP2_TOKEN_UPGRADE;
250
368
      }
251
435
      break;
252
435
    case 'h':
253
407
      if (memeq("refres", name, 6)) {
254
208
        return NGHTTP2_TOKEN_REFRESH;
255
208
      }
256
199
      break;
257
1.64k
    case 'r':
258
1.64k
      if (memeq("refere", name, 6)) {
259
417
        return NGHTTP2_TOKEN_REFERER;
260
417
      }
261
1.22k
      break;
262
14.3k
    case 's':
263
14.3k
      if (memeq(":statu", name, 6)) {
264
282
        return NGHTTP2_TOKEN__STATUS;
265
282
      }
266
14.1k
      if (memeq("expire", name, 6)) {
267
432
        return NGHTTP2_TOKEN_EXPIRES;
268
432
      }
269
13.6k
      break;
270
18.5k
    }
271
16.4k
    break;
272
16.4k
  case 8:
273
5.11k
    switch (name[7]) {
274
1.71k
    case 'e':
275
1.71k
      if (memeq("if-rang", name, 7)) {
276
206
        return NGHTTP2_TOKEN_IF_RANGE;
277
206
      }
278
1.51k
      break;
279
1.51k
    case 'h':
280
389
      if (memeq("if-matc", name, 7)) {
281
194
        return NGHTTP2_TOKEN_IF_MATCH;
282
194
      }
283
195
      break;
284
1.07k
    case 'n':
285
1.07k
      if (memeq("locatio", name, 7)) {
286
794
        return NGHTTP2_TOKEN_LOCATION;
287
794
      }
288
282
      break;
289
1.48k
    case 'y':
290
1.48k
      if (memeq("priorit", name, 7)) {
291
1.27k
        return NGHTTP2_TOKEN_PRIORITY;
292
1.27k
      }
293
212
      break;
294
5.11k
    }
295
2.65k
    break;
296
2.65k
  case 9:
297
1.68k
    switch (name[8]) {
298
1.07k
    case 'l':
299
1.07k
      if (memeq(":protoco", name, 8)) {
300
784
        return NGHTTP2_TOKEN__PROTOCOL;
301
784
      }
302
287
      break;
303
1.68k
    }
304
897
    break;
305
3.03k
  case 10:
306
3.03k
    switch (name[9]) {
307
1.01k
    case 'e':
308
1.01k
      if (memeq("keep-aliv", name, 9)) {
309
342
        return NGHTTP2_TOKEN_KEEP_ALIVE;
310
342
      }
311
676
      if (memeq("set-cooki", name, 9)) {
312
194
        return NGHTTP2_TOKEN_SET_COOKIE;
313
194
      }
314
482
      break;
315
522
    case 'n':
316
522
      if (memeq("connectio", name, 9)) {
317
210
        return NGHTTP2_TOKEN_CONNECTION;
318
210
      }
319
312
      break;
320
595
    case 't':
321
595
      if (memeq("user-agen", name, 9)) {
322
373
        return NGHTTP2_TOKEN_USER_AGENT;
323
373
      }
324
222
      break;
325
562
    case 'y':
326
562
      if (memeq(":authorit", name, 9)) {
327
202
        return NGHTTP2_TOKEN__AUTHORITY;
328
202
      }
329
360
      break;
330
3.03k
    }
331
1.71k
    break;
332
1.71k
  case 11:
333
801
    switch (name[10]) {
334
399
    case 'r':
335
399
      if (memeq("retry-afte", name, 10)) {
336
194
        return NGHTTP2_TOKEN_RETRY_AFTER;
337
194
      }
338
205
      break;
339
801
    }
340
607
    break;
341
1.04k
  case 12:
342
1.04k
    switch (name[11]) {
343
413
    case 'e':
344
413
      if (memeq("content-typ", name, 11)) {
345
194
        return NGHTTP2_TOKEN_CONTENT_TYPE;
346
194
      }
347
219
      break;
348
400
    case 's':
349
400
      if (memeq("max-forward", name, 11)) {
350
194
        return NGHTTP2_TOKEN_MAX_FORWARDS;
351
194
      }
352
206
      break;
353
1.04k
    }
354
658
    break;
355
3.75k
  case 13:
356
3.75k
    switch (name[12]) {
357
436
    case 'd':
358
436
      if (memeq("last-modifie", name, 12)) {
359
197
        return NGHTTP2_TOKEN_LAST_MODIFIED;
360
197
      }
361
239
      break;
362
503
    case 'e':
363
503
      if (memeq("content-rang", name, 12)) {
364
194
        return NGHTTP2_TOKEN_CONTENT_RANGE;
365
194
      }
366
309
      break;
367
552
    case 'h':
368
552
      if (memeq("if-none-matc", name, 12)) {
369
194
        return NGHTTP2_TOKEN_IF_NONE_MATCH;
370
194
      }
371
358
      break;
372
421
    case 'l':
373
421
      if (memeq("cache-contro", name, 12)) {
374
216
        return NGHTTP2_TOKEN_CACHE_CONTROL;
375
216
      }
376
205
      break;
377
1.15k
    case 'n':
378
1.15k
      if (memeq("authorizatio", name, 12)) {
379
693
        return NGHTTP2_TOKEN_AUTHORIZATION;
380
693
      }
381
462
      break;
382
462
    case 's':
383
421
      if (memeq("accept-range", name, 12)) {
384
194
        return NGHTTP2_TOKEN_ACCEPT_RANGES;
385
194
      }
386
227
      break;
387
3.75k
    }
388
2.06k
    break;
389
2.06k
  case 14:
390
2.00k
    switch (name[13]) {
391
428
    case 'h':
392
428
      if (memeq("content-lengt", name, 13)) {
393
194
        return NGHTTP2_TOKEN_CONTENT_LENGTH;
394
194
      }
395
234
      break;
396
1.25k
    case 't':
397
1.25k
      if (memeq("accept-charse", name, 13)) {
398
922
        return NGHTTP2_TOKEN_ACCEPT_CHARSET;
399
922
      }
400
332
      break;
401
2.00k
    }
402
884
    break;
403
1.23k
  case 15:
404
1.23k
    switch (name[14]) {
405
614
    case 'e':
406
614
      if (memeq("accept-languag", name, 14)) {
407
249
        return NGHTTP2_TOKEN_ACCEPT_LANGUAGE;
408
249
      }
409
365
      break;
410
404
    case 'g':
411
404
      if (memeq("accept-encodin", name, 14)) {
412
199
        return NGHTTP2_TOKEN_ACCEPT_ENCODING;
413
199
      }
414
205
      break;
415
1.23k
    }
416
790
    break;
417
6.63k
  case 16:
418
6.63k
    switch (name[15]) {
419
2.93k
    case 'e':
420
2.93k
      if (memeq("content-languag", name, 15)) {
421
285
        return NGHTTP2_TOKEN_CONTENT_LANGUAGE;
422
285
      }
423
2.65k
      if (memeq("www-authenticat", name, 15)) {
424
1.57k
        return NGHTTP2_TOKEN_WWW_AUTHENTICATE;
425
1.57k
      }
426
1.07k
      break;
427
1.07k
    case 'g':
428
496
      if (memeq("content-encodin", name, 15)) {
429
255
        return NGHTTP2_TOKEN_CONTENT_ENCODING;
430
255
      }
431
241
      break;
432
802
    case 'n':
433
802
      if (memeq("content-locatio", name, 15)) {
434
220
        return NGHTTP2_TOKEN_CONTENT_LOCATION;
435
220
      }
436
582
      if (memeq("proxy-connectio", name, 15)) {
437
346
        return NGHTTP2_TOKEN_PROXY_CONNECTION;
438
346
      }
439
236
      break;
440
6.63k
    }
441
3.95k
    break;
442
3.95k
  case 17:
443
1.64k
    switch (name[16]) {
444
501
    case 'e':
445
501
      if (memeq("if-modified-sinc", name, 16)) {
446
240
        return NGHTTP2_TOKEN_IF_MODIFIED_SINCE;
447
240
      }
448
261
      break;
449
736
    case 'g':
450
736
      if (memeq("transfer-encodin", name, 16)) {
451
503
        return NGHTTP2_TOKEN_TRANSFER_ENCODING;
452
503
      }
453
233
      break;
454
1.64k
    }
455
904
    break;
456
904
  case 18:
457
746
    switch (name[17]) {
458
501
    case 'e':
459
501
      if (memeq("proxy-authenticat", name, 17)) {
460
270
        return NGHTTP2_TOKEN_PROXY_AUTHENTICATE;
461
270
      }
462
231
      break;
463
746
    }
464
476
    break;
465
1.92k
  case 19:
466
1.92k
    switch (name[18]) {
467
746
    case 'e':
468
746
      if (memeq("if-unmodified-sinc", name, 18)) {
469
411
        return NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE;
470
411
      }
471
335
      break;
472
754
    case 'n':
473
754
      if (memeq("content-dispositio", name, 18)) {
474
203
        return NGHTTP2_TOKEN_CONTENT_DISPOSITION;
475
203
      }
476
551
      if (memeq("proxy-authorizatio", name, 18)) {
477
318
        return NGHTTP2_TOKEN_PROXY_AUTHORIZATION;
478
318
      }
479
233
      break;
480
1.92k
    }
481
988
    break;
482
988
  case 25:
483
644
    switch (name[24]) {
484
431
    case 'y':
485
431
      if (memeq("strict-transport-securit", name, 24)) {
486
213
        return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY;
487
213
      }
488
218
      break;
489
644
    }
490
431
    break;
491
2.90k
  case 27:
492
2.90k
    switch (name[26]) {
493
2.43k
    case 'n':
494
2.43k
      if (memeq("access-control-allow-origi", name, 26)) {
495
198
        return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
496
198
      }
497
2.23k
      break;
498
2.90k
    }
499
2.70k
    break;
500
110k
  }
501
89.4k
  return -1;
502
110k
}
503
504
28.1k
void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv) {
505
28.1k
  *ent = (nghttp2_hd_entry){
506
28.1k
    .nv = *nv,
507
28.1k
    .cnv =
508
28.1k
      {
509
28.1k
        .name = nv->name->base,
510
28.1k
        .value = nv->value->base,
511
28.1k
        .namelen = nv->name->len,
512
28.1k
        .valuelen = nv->value->len,
513
28.1k
        .flags = nv->flags,
514
28.1k
      },
515
28.1k
  };
516
517
28.1k
  nghttp2_rcbuf_incref(ent->nv.name);
518
28.1k
  nghttp2_rcbuf_incref(ent->nv.value);
519
28.1k
}
520
521
28.1k
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) {
522
28.1k
  nghttp2_rcbuf_decref(ent->nv.value);
523
28.1k
  nghttp2_rcbuf_decref(ent->nv.name);
524
28.1k
}
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.87k
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
19.7k
                           nghttp2_mem *mem) {
613
19.7k
  size_t size;
614
19.7k
  const size_t max_size = SIZE_MAX / sizeof(nghttp2_hd_entry *);
615
616
19.7k
  if (bufsize > max_size) {
617
0
    return NGHTTP2_ERR_NOMEM;
618
0
  }
619
620
158k
  for (size = 1; size < bufsize; size <<= 1)
621
138k
    ;
622
623
19.7k
  if (size > max_size) {
624
0
    return NGHTTP2_ERR_NOMEM;
625
0
  }
626
627
19.7k
  ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
628
19.7k
  if (ringbuf->buffer == NULL) {
629
0
    return NGHTTP2_ERR_NOMEM;
630
0
  }
631
19.7k
  ringbuf->mask = size - 1;
632
19.7k
  ringbuf->first = 0;
633
19.7k
  ringbuf->len = 0;
634
19.7k
  return 0;
635
19.7k
}
636
637
static nghttp2_hd_entry *hd_ringbuf_get(nghttp2_hd_ringbuf *ringbuf,
638
143k
                                        size_t idx) {
639
143k
  assert(idx < ringbuf->len);
640
143k
  return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask];
641
143k
}
642
643
static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
644
28.1k
                              nghttp2_mem *mem) {
645
28.1k
  size_t i;
646
28.1k
  size_t size;
647
28.1k
  nghttp2_hd_entry **buffer;
648
649
28.1k
  if (ringbuf->mask + 1 >= bufsize) {
650
28.1k
    return 0;
651
28.1k
  }
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
19.7k
static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
669
19.7k
  size_t i;
670
19.7k
  if (ringbuf == NULL) {
671
0
    return;
672
0
  }
673
33.0k
  for (i = 0; i < ringbuf->len; ++i) {
674
13.2k
    nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
675
676
13.2k
    nghttp2_hd_entry_free(ent);
677
13.2k
    nghttp2_mem_free(mem, ent);
678
13.2k
  }
679
19.7k
  nghttp2_mem_free(mem, ringbuf->buffer);
680
19.7k
}
681
682
static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf,
683
28.1k
                                 nghttp2_hd_entry *ent, nghttp2_mem *mem) {
684
28.1k
  int rv;
685
686
28.1k
  rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem);
687
688
28.1k
  if (rv != 0) {
689
0
    return rv;
690
0
  }
691
692
28.1k
  ringbuf->buffer[--ringbuf->first & ringbuf->mask] = ent;
693
28.1k
  ++ringbuf->len;
694
695
28.1k
  return 0;
696
28.1k
}
697
698
14.8k
static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) {
699
14.8k
  assert(ringbuf->len > 0);
700
14.8k
  --ringbuf->len;
701
14.8k
}
702
703
19.7k
static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
704
19.7k
  int rv;
705
19.7k
  context->mem = mem;
706
19.7k
  context->bad = 0;
707
19.7k
  context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
708
19.7k
  rv = hd_ringbuf_init(
709
19.7k
    &context->hd_table,
710
19.7k
    context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
711
19.7k
  if (rv != 0) {
712
0
    return rv;
713
0
  }
714
715
19.7k
  context->hd_table_bufsize = 0;
716
19.7k
  context->next_seq = 0;
717
718
19.7k
  return 0;
719
19.7k
}
720
721
19.7k
static void hd_context_free(nghttp2_hd_context *context) {
722
19.7k
  hd_ringbuf_free(&context->hd_table, context->mem);
723
19.7k
}
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.87k
                             nghttp2_mem *mem) {
733
9.87k
  int rv;
734
9.87k
  rv = hd_context_init(&deflater->ctx, mem);
735
9.87k
  if (rv != 0) {
736
0
    return rv;
737
0
  }
738
739
9.87k
  hd_map_init(&deflater->map);
740
741
9.87k
  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.87k
  } else {
745
9.87k
    deflater->notify_table_size_change = 0;
746
9.87k
  }
747
748
9.87k
  deflater->deflate_hd_table_bufsize_max = max_deflate_dynamic_table_size;
749
9.87k
  deflater->min_hd_table_bufsize_max = UINT32_MAX;
750
751
9.87k
  return 0;
752
9.87k
}
753
754
9.87k
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
755
9.87k
  int rv;
756
757
9.87k
  rv = hd_context_init(&inflater->ctx, mem);
758
9.87k
  if (rv != 0) {
759
0
    goto fail;
760
0
  }
761
762
9.87k
  inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
763
9.87k
  inflater->min_hd_table_bufsize_max = UINT32_MAX;
764
765
9.87k
  inflater->nv_name_keep = NULL;
766
9.87k
  inflater->nv_value_keep = NULL;
767
768
9.87k
  inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
769
9.87k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
770
771
9.87k
  nghttp2_buf_init(&inflater->namebuf);
772
9.87k
  nghttp2_buf_init(&inflater->valuebuf);
773
774
9.87k
  inflater->namercbuf = NULL;
775
9.87k
  inflater->valuercbuf = NULL;
776
777
9.87k
  inflater->huffman_encoded = 0;
778
9.87k
  inflater->index = 0;
779
9.87k
  inflater->left = 0;
780
9.87k
  inflater->shift = 0;
781
9.87k
  inflater->index_required = 0;
782
9.87k
  inflater->no_index = 0;
783
784
9.87k
  return 0;
785
786
0
fail:
787
0
  return rv;
788
9.87k
}
789
790
649k
static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
791
649k
  nghttp2_rcbuf_decref(inflater->nv_value_keep);
792
649k
  nghttp2_rcbuf_decref(inflater->nv_name_keep);
793
794
649k
  inflater->nv_value_keep = NULL;
795
649k
  inflater->nv_name_keep = NULL;
796
649k
}
797
798
9.87k
void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
799
9.87k
  hd_context_free(&deflater->ctx);
800
9.87k
}
801
802
9.87k
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
803
9.87k
  hd_inflate_keep_free(inflater);
804
805
9.87k
  nghttp2_rcbuf_decref(inflater->valuercbuf);
806
9.87k
  nghttp2_rcbuf_decref(inflater->namercbuf);
807
808
9.87k
  hd_context_free(&inflater->ctx);
809
9.87k
}
810
811
45.5k
static size_t entry_room(size_t namelen, size_t valuelen) {
812
45.5k
  return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
813
45.5k
}
814
815
386k
static void emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
816
386k
  DEBUGF("inflatehd: header emission: %s: %s\n", nv->name->base,
817
386k
         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
386k
  *nv_out = *nv;
821
386k
}
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
538k
                                   size_t prefix) {
886
538k
  uint32_t k = (uint8_t)((1 << prefix) - 1);
887
538k
  uint32_t n = initial;
888
538k
  const uint8_t *start = in;
889
890
538k
  *shift_ptr = 0;
891
538k
  *fin = 0;
892
893
538k
  if (n == 0) {
894
537k
    if ((*in & k) != k) {
895
530k
      *res = (*in) & k;
896
530k
      *fin = 1;
897
530k
      return 1;
898
530k
    }
899
900
7.36k
    n = k;
901
902
7.36k
    if (++in == last) {
903
140
      *res = n;
904
140
      return (nghttp2_ssize)(in - start);
905
140
    }
906
7.36k
  }
907
908
22.2k
  for (; in != last; ++in, shift += 7) {
909
20.7k
    uint32_t add = *in & 0x7F;
910
911
20.7k
    if (shift >= 32) {
912
25
      DEBUGF("inflate: shift exponent overflow\n");
913
25
      return -1;
914
25
    }
915
916
20.7k
    if ((UINT32_MAX >> shift) < add) {
917
42
      DEBUGF("inflate: integer overflow on shift\n");
918
42
      return -1;
919
42
    }
920
921
20.6k
    add <<= shift;
922
923
20.6k
    if (UINT32_MAX - add < n) {
924
43
      DEBUGF("inflate: integer overflow on addition\n");
925
43
      return -1;
926
43
    }
927
928
20.6k
    n += add;
929
930
20.6k
    if ((*in & (1 << 7)) == 0) {
931
6.63k
      break;
932
6.63k
    }
933
20.6k
  }
934
935
8.09k
  *shift_ptr = shift;
936
937
8.09k
  if (in == last) {
938
1.45k
    *res = n;
939
1.45k
    return (nghttp2_ssize)(in - start);
940
1.45k
  }
941
942
6.63k
  *res = n;
943
6.63k
  *fin = 1;
944
6.63k
  return (nghttp2_ssize)(in + 1 - start);
945
8.09k
}
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
30.7k
                                    uint32_t hash) {
1133
30.7k
  int rv;
1134
30.7k
  nghttp2_hd_entry *new_ent;
1135
30.7k
  size_t room;
1136
30.7k
  nghttp2_mem *mem;
1137
1138
30.7k
  mem = context->mem;
1139
30.7k
  room = entry_room(nv->name->len, nv->value->len);
1140
1141
44.7k
  while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
1142
16.6k
         context->hd_table.len > 0) {
1143
14.0k
    size_t idx = context->hd_table.len - 1;
1144
14.0k
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1145
1146
14.0k
    context->hd_table_bufsize -=
1147
14.0k
      entry_room(ent->nv.name->len, ent->nv.value->len);
1148
1149
14.0k
    DEBUGF("hpack: remove item from header table: %s: %s\n",
1150
14.0k
           (char *)ent->nv.name->base, (char *)ent->nv.value->base);
1151
1152
14.0k
    hd_ringbuf_pop_back(&context->hd_table);
1153
14.0k
    if (map) {
1154
0
      hd_map_remove(map, ent);
1155
0
    }
1156
1157
14.0k
    nghttp2_hd_entry_free(ent);
1158
14.0k
    nghttp2_mem_free(mem, ent);
1159
14.0k
  }
1160
1161
30.7k
  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
2.56k
    return 0;
1165
2.56k
  }
1166
1167
28.1k
  new_ent = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry));
1168
28.1k
  if (new_ent == NULL) {
1169
0
    return NGHTTP2_ERR_NOMEM;
1170
0
  }
1171
1172
28.1k
  nghttp2_hd_entry_init(new_ent, nv);
1173
1174
28.1k
  rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
1175
1176
28.1k
  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
28.1k
  new_ent->seq = context->next_seq++;
1184
28.1k
  new_ent->hash = hash;
1185
1186
28.1k
  if (map) {
1187
0
    hd_map_insert(map, new_ent);
1188
0
  }
1189
1190
28.1k
  context->hd_table_bufsize += room;
1191
1192
28.1k
  return 0;
1193
28.1k
}
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
5.18k
                                         nghttp2_hd_map *map) {
1254
5.18k
  nghttp2_mem *mem;
1255
1256
5.18k
  mem = context->mem;
1257
1258
6.01k
  while (context->hd_table_bufsize > context->hd_table_bufsize_max &&
1259
824
         context->hd_table.len > 0) {
1260
824
    size_t idx = context->hd_table.len - 1;
1261
824
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1262
824
    context->hd_table_bufsize -=
1263
824
      entry_room(ent->nv.name->len, ent->nv.value->len);
1264
824
    hd_ringbuf_pop_back(&context->hd_table);
1265
824
    if (map) {
1266
0
      hd_map_remove(map, ent);
1267
0
    }
1268
1269
824
    nghttp2_hd_entry_free(ent);
1270
824
    nghttp2_mem_free(mem, ent);
1271
824
  }
1272
5.18k
}
1273
1274
int nghttp2_hd_deflate_change_table_size(
1275
1.96k
  nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
1276
1.96k
  size_t next_bufsize = nghttp2_min_size(
1277
1.96k
    settings_max_dynamic_table_size, deflater->deflate_hd_table_bufsize_max);
1278
1279
1.96k
  deflater->ctx.hd_table_bufsize_max = next_bufsize;
1280
1281
1.96k
  deflater->min_hd_table_bufsize_max =
1282
1.96k
    nghttp2_min_size(deflater->min_hd_table_bufsize_max, next_bufsize);
1283
1284
1.96k
  deflater->notify_table_size_change = 1;
1285
1286
1.96k
  hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
1287
1.96k
  return 0;
1288
1.96k
}
1289
1290
int nghttp2_hd_inflate_change_table_size(
1291
142
  nghttp2_hd_inflater *inflater, size_t settings_max_dynamic_table_size) {
1292
142
  switch (inflater->state) {
1293
32
  case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1294
142
  case NGHTTP2_HD_STATE_INFLATE_START:
1295
142
    break;
1296
0
  default:
1297
0
    return NGHTTP2_ERR_INVALID_STATE;
1298
142
  }
1299
1300
142
  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
142
  if (inflater->ctx.hd_table_bufsize_max > settings_max_dynamic_table_size) {
1310
108
    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
108
    inflater->min_hd_table_bufsize_max = settings_max_dynamic_table_size;
1314
1315
108
    inflater->ctx.hd_table_bufsize_max = settings_max_dynamic_table_size;
1316
1317
108
    hd_context_shrink_table_size(&inflater->ctx, NULL);
1318
108
  }
1319
1320
142
  return 0;
1321
142
}
1322
1323
#define INDEX_RANGE_VALID(context, idx)                                        \
1324
0
  ((idx) < (context)->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH)
1325
1326
277k
static size_t get_max_index(nghttp2_hd_context *context) {
1327
277k
  return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH;
1328
277k
}
1329
1330
276k
nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
1331
276k
  assert(INDEX_RANGE_VALID(context, idx));
1332
276k
  if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1333
115k
    return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
1334
115k
      ->nv;
1335
160k
  } else {
1336
160k
    const nghttp2_hd_static_entry *ent = &static_table[idx];
1337
160k
    return (nghttp2_hd_nv){
1338
160k
      .name = (nghttp2_rcbuf *)&ent->name,
1339
160k
      .value = (nghttp2_rcbuf *)&ent->value,
1340
160k
      .token = ent->token,
1341
160k
      .flags = NGHTTP2_NV_FLAG_NONE,
1342
160k
    };
1343
160k
  }
1344
276k
}
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
257k
                                           const uint8_t *in) {
1670
257k
  inflater->huffman_encoded = (*in & (1 << 7)) != 0;
1671
257k
}
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
538k
                                         size_t maxlen) {
1690
538k
  nghttp2_ssize rv;
1691
538k
  uint32_t out;
1692
1693
538k
  *rfin = 0;
1694
1695
538k
  rv = decode_length(&out, &inflater->shift, rfin, (uint32_t)inflater->left,
1696
538k
                     inflater->shift, in, last, prefix);
1697
1698
538k
  if (rv == -1) {
1699
110
    DEBUGF("inflatehd: integer decoding failed\n");
1700
110
    return NGHTTP2_ERR_HEADER_COMP;
1701
110
  }
1702
1703
538k
  if (out > maxlen) {
1704
951
    DEBUGF("inflatehd: integer exceeded the maximum value %zu\n", maxlen);
1705
951
    return NGHTTP2_ERR_HEADER_COMP;
1706
951
  }
1707
1708
537k
  inflater->left = out;
1709
1710
537k
  DEBUGF("inflatehd: decoded integer is %u\n", out);
1711
1712
537k
  return rv;
1713
538k
}
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
18.7k
                                          const uint8_t *last) {
1731
18.7k
  nghttp2_ssize readlen;
1732
18.7k
  int fin = 0;
1733
18.7k
  if ((size_t)(last - in) >= inflater->left) {
1734
18.5k
    last = in + inflater->left;
1735
18.5k
    fin = 1;
1736
18.5k
  }
1737
18.7k
  readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
1738
18.7k
                                   (size_t)(last - in), fin);
1739
1740
18.7k
  if (readlen < 0) {
1741
46
    DEBUGF("inflatehd: huffman decoding failed\n");
1742
46
    return readlen;
1743
46
  }
1744
18.7k
  if (nghttp2_hd_huff_decode_failure_state(&inflater->huff_decode_ctx)) {
1745
17
    DEBUGF("inflatehd: huffman decoding failed\n");
1746
17
    return NGHTTP2_ERR_HEADER_COMP;
1747
17
  }
1748
1749
18.6k
  inflater->left -= (size_t)readlen;
1750
18.6k
  return readlen;
1751
18.7k
}
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
238k
                                     const uint8_t *last) {
1768
238k
  size_t len = nghttp2_min_size((size_t)(last - in), inflater->left);
1769
1770
238k
  buf->last = nghttp2_cpymem(buf->last, in, len);
1771
1772
238k
  inflater->left -= len;
1773
238k
  return (nghttp2_ssize)len;
1774
238k
}
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
241k
                                      nghttp2_hd_nv *nv_out) {
1782
241k
  nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1783
1784
241k
  emit_header(nv_out, &nv);
1785
241k
}
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
110k
                                     nghttp2_hd_nv *nv_out) {
1800
110k
  nghttp2_hd_nv nv;
1801
110k
  int rv;
1802
1803
110k
  if (inflater->no_index) {
1804
2.72k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1805
108k
  } else {
1806
108k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1807
108k
  }
1808
1809
110k
  nv.name = inflater->namercbuf;
1810
110k
  nv.value = inflater->valuercbuf;
1811
110k
  nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len);
1812
1813
110k
  if (inflater->index_required) {
1814
7.94k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1815
1816
7.94k
    if (rv != 0) {
1817
0
      return rv;
1818
0
    }
1819
7.94k
  }
1820
1821
110k
  emit_header(nv_out, &nv);
1822
1823
110k
  inflater->nv_name_keep = nv.name;
1824
110k
  inflater->nv_value_keep = nv.value;
1825
1826
110k
  inflater->namercbuf = NULL;
1827
110k
  inflater->valuercbuf = NULL;
1828
1829
110k
  return 0;
1830
110k
}
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
34.7k
                                     nghttp2_hd_nv *nv_out) {
1845
34.7k
  nghttp2_hd_nv nv;
1846
34.7k
  int rv;
1847
1848
34.7k
  nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1849
1850
34.7k
  if (inflater->no_index) {
1851
1.72k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1852
32.9k
  } else {
1853
32.9k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1854
32.9k
  }
1855
1856
34.7k
  nghttp2_rcbuf_incref(nv.name);
1857
1858
34.7k
  nv.value = inflater->valuercbuf;
1859
1860
34.7k
  if (inflater->index_required) {
1861
22.7k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1862
22.7k
    if (rv != 0) {
1863
0
      nghttp2_rcbuf_decref(nv.name);
1864
0
      return NGHTTP2_ERR_NOMEM;
1865
0
    }
1866
22.7k
  }
1867
1868
34.7k
  emit_header(nv_out, &nv);
1869
1870
34.7k
  inflater->nv_name_keep = nv.name;
1871
34.7k
  inflater->nv_value_keep = nv.value;
1872
1873
34.7k
  inflater->valuercbuf = NULL;
1874
1875
34.7k
  return 0;
1876
34.7k
}
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
516k
                                       size_t inlen, int in_final) {
1923
516k
  nghttp2_ssize rv = 0;
1924
516k
  const uint8_t *first = in;
1925
516k
  const uint8_t *last = in + inlen;
1926
516k
  int rfin = 0;
1927
516k
  int busy = 0;
1928
516k
  nghttp2_mem *mem;
1929
1930
516k
  mem = inflater->ctx.mem;
1931
1932
516k
  if (inflater->ctx.bad) {
1933
0
    return NGHTTP2_ERR_HEADER_COMP;
1934
0
  }
1935
1936
516k
  DEBUGF("inflatehd: start state=%d\n", inflater->state);
1937
516k
  hd_inflate_keep_free(inflater);
1938
516k
  *inflate_flags = NGHTTP2_HD_INFLATE_NONE;
1939
1.31M
  for (; in != last || busy;) {
1940
1.18M
    busy = 0;
1941
1.18M
    switch (inflater->state) {
1942
19
    case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1943
19
      if ((*in & 0xE0U) != 0x20U) {
1944
4
        DEBUGF("inflatehd: header table size change was expected, but saw "
1945
4
               "0x%02x as first byte",
1946
4
               *in);
1947
4
        rv = NGHTTP2_ERR_HEADER_COMP;
1948
4
        goto fail;
1949
4
      }
1950
    /* fall through */
1951
116k
    case NGHTTP2_HD_STATE_INFLATE_START:
1952
391k
    case NGHTTP2_HD_STATE_OPCODE:
1953
391k
      if ((*in & 0xE0U) == 0x20U) {
1954
3.46k
        DEBUGF("inflatehd: header table size change\n");
1955
3.46k
        if (inflater->state == NGHTTP2_HD_STATE_OPCODE) {
1956
42
          DEBUGF("inflatehd: header table size change must appear at the head "
1957
42
                 "of header block\n");
1958
42
          rv = NGHTTP2_ERR_HEADER_COMP;
1959
42
          goto fail;
1960
42
        }
1961
3.42k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1962
3.42k
        inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
1963
388k
      } else if (*in & 0x80U) {
1964
241k
        DEBUGF("inflatehd: indexed repr\n");
1965
241k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1966
241k
        inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1967
241k
      } else {
1968
146k
        if (*in == 0x40U || *in == 0 || *in == 0x10U) {
1969
111k
          DEBUGF("inflatehd: literal header repr - new name\n");
1970
111k
          inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
1971
111k
          inflater->state = NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN;
1972
111k
        } else {
1973
35.4k
          DEBUGF("inflatehd: literal header repr - indexed name\n");
1974
35.4k
          inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
1975
35.4k
          inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1976
35.4k
        }
1977
146k
        inflater->index_required = (*in & 0x40) != 0;
1978
146k
        inflater->no_index = (*in & 0xF0U) == 0x10U;
1979
146k
        DEBUGF("inflatehd: indexing required=%d, no_index=%d\n",
1980
146k
               inflater->index_required, inflater->no_index);
1981
146k
        if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1982
111k
          ++in;
1983
111k
        }
1984
146k
      }
1985
391k
      inflater->left = 0;
1986
391k
      inflater->shift = 0;
1987
391k
      break;
1988
3.94k
    case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
1989
3.94k
      rfin = 0;
1990
3.94k
      rv = hd_inflate_read_len(
1991
3.94k
        inflater, &rfin, in, last, 5,
1992
3.94k
        nghttp2_min_size(inflater->min_hd_table_bufsize_max,
1993
3.94k
                         inflater->settings_hd_table_bufsize_max));
1994
3.94k
      if (rv < 0) {
1995
254
        goto fail;
1996
254
      }
1997
3.69k
      in += rv;
1998
3.69k
      if (!rfin) {
1999
574
        goto almost_ok;
2000
574
      }
2001
3.11k
      DEBUGF("inflatehd: table_size=%zu\n", inflater->left);
2002
3.11k
      inflater->min_hd_table_bufsize_max = UINT32_MAX;
2003
3.11k
      inflater->ctx.hd_table_bufsize_max = inflater->left;
2004
3.11k
      hd_context_shrink_table_size(&inflater->ctx, NULL);
2005
3.11k
      inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
2006
3.11k
      break;
2007
277k
    case NGHTTP2_HD_STATE_READ_INDEX: {
2008
277k
      size_t prefixlen;
2009
2010
277k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
2011
241k
        prefixlen = 7;
2012
241k
      } else if (inflater->index_required) {
2013
23.0k
        prefixlen = 6;
2014
23.0k
      } else {
2015
12.4k
        prefixlen = 4;
2016
12.4k
      }
2017
2018
277k
      rfin = 0;
2019
277k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
2020
277k
                               get_max_index(&inflater->ctx));
2021
277k
      if (rv < 0) {
2022
400
        goto fail;
2023
400
      }
2024
2025
276k
      in += rv;
2026
2027
276k
      if (!rfin) {
2028
165
        goto almost_ok;
2029
165
      }
2030
2031
276k
      if (inflater->left == 0) {
2032
21
        rv = NGHTTP2_ERR_HEADER_COMP;
2033
21
        goto fail;
2034
21
      }
2035
2036
276k
      DEBUGF("inflatehd: index=%zu\n", inflater->left);
2037
276k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
2038
241k
        inflater->index = inflater->left;
2039
241k
        --inflater->index;
2040
2041
241k
        hd_inflate_commit_indexed(inflater, nv_out);
2042
2043
241k
        inflater->state = NGHTTP2_HD_STATE_OPCODE;
2044
241k
        *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2045
241k
        return (nghttp2_ssize)(in - first);
2046
241k
      } else {
2047
35.2k
        inflater->index = inflater->left;
2048
35.2k
        --inflater->index;
2049
2050
35.2k
        inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2051
35.2k
      }
2052
35.2k
      break;
2053
276k
    }
2054
111k
    case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
2055
111k
      hd_inflate_set_huffman_encoded(inflater, in);
2056
111k
      inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
2057
111k
      inflater->left = 0;
2058
111k
      inflater->shift = 0;
2059
111k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2060
    /* Fall through */
2061
111k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN:
2062
111k
      rfin = 0;
2063
111k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2064
111k
      if (rv < 0) {
2065
210
        goto fail;
2066
210
      }
2067
111k
      in += rv;
2068
111k
      if (!rfin) {
2069
208
        DEBUGF("inflatehd: integer not fully decoded. current=%zu\n",
2070
208
               inflater->left);
2071
2072
208
        goto almost_ok;
2073
208
      }
2074
2075
111k
      if (inflater->huffman_encoded) {
2076
7.96k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2077
2078
7.96k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
2079
2080
7.96k
        rv = nghttp2_rcbuf_new(
2081
7.96k
          &inflater->namercbuf,
2082
7.96k
          nghttp2_huff_estimate_decode_length(inflater->left) + 1, mem);
2083
103k
      } else {
2084
103k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
2085
103k
        rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
2086
103k
      }
2087
2088
111k
      if (rv != 0) {
2089
0
        goto fail;
2090
0
      }
2091
2092
111k
      nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base,
2093
111k
                            inflater->namercbuf->len);
2094
2095
111k
      break;
2096
7.93k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
2097
7.93k
      rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
2098
7.93k
      if (rv < 0) {
2099
21
        goto fail;
2100
21
      }
2101
2102
7.91k
      in += rv;
2103
2104
7.91k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2105
2106
7.91k
      if (inflater->left) {
2107
73
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2108
2109
73
        goto almost_ok;
2110
73
      }
2111
2112
7.83k
      *inflater->namebuf.last = '\0';
2113
7.83k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2114
2115
7.83k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2116
2117
7.83k
      break;
2118
103k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
2119
103k
      rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
2120
103k
      if (rv < 0) {
2121
0
        goto fail;
2122
0
      }
2123
2124
103k
      in += rv;
2125
2126
103k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2127
103k
      if (inflater->left) {
2128
92
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2129
2130
92
        goto almost_ok;
2131
92
      }
2132
2133
103k
      *inflater->namebuf.last = '\0';
2134
103k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2135
2136
103k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2137
2138
103k
      break;
2139
146k
    case NGHTTP2_HD_STATE_CHECK_VALUELEN:
2140
146k
      hd_inflate_set_huffman_encoded(inflater, in);
2141
146k
      inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
2142
146k
      inflater->left = 0;
2143
146k
      inflater->shift = 0;
2144
146k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2145
    /* Fall through */
2146
146k
    case NGHTTP2_HD_STATE_READ_VALUELEN:
2147
146k
      rfin = 0;
2148
146k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2149
146k
      if (rv < 0) {
2150
197
        goto fail;
2151
197
      }
2152
2153
145k
      in += rv;
2154
2155
145k
      if (!rfin) {
2156
205
        goto almost_ok;
2157
205
      }
2158
2159
145k
      DEBUGF("inflatehd: valuelen=%zu\n", inflater->left);
2160
2161
145k
      if (inflater->huffman_encoded) {
2162
10.7k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2163
2164
10.7k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
2165
2166
10.7k
        rv = nghttp2_rcbuf_new(
2167
10.7k
          &inflater->valuercbuf,
2168
10.7k
          nghttp2_huff_estimate_decode_length(inflater->left) + 1, mem);
2169
134k
      } else {
2170
134k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
2171
2172
134k
        rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem);
2173
134k
      }
2174
2175
145k
      if (rv != 0) {
2176
0
        goto fail;
2177
0
      }
2178
2179
145k
      nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base,
2180
145k
                            inflater->valuercbuf->len);
2181
2182
145k
      busy = 1;
2183
2184
145k
      break;
2185
10.8k
    case NGHTTP2_HD_STATE_READ_VALUEHUFF:
2186
10.8k
      rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
2187
10.8k
      if (rv < 0) {
2188
42
        goto fail;
2189
42
      }
2190
2191
10.7k
      in += rv;
2192
2193
10.7k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2194
2195
10.7k
      if (inflater->left) {
2196
99
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2197
2198
99
        goto almost_ok;
2199
99
      }
2200
2201
10.6k
      *inflater->valuebuf.last = '\0';
2202
10.6k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2203
2204
10.6k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2205
5.75k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2206
5.75k
      } else {
2207
4.92k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2208
4.92k
      }
2209
2210
10.6k
      if (rv != 0) {
2211
0
        goto fail;
2212
0
      }
2213
2214
10.6k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2215
10.6k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2216
2217
10.6k
      return (nghttp2_ssize)(in - first);
2218
135k
    case NGHTTP2_HD_STATE_READ_VALUE:
2219
135k
      rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
2220
135k
      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
135k
      in += rv;
2227
2228
135k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2229
2230
135k
      if (inflater->left) {
2231
219
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2232
219
        goto almost_ok;
2233
219
      }
2234
2235
134k
      *inflater->valuebuf.last = '\0';
2236
134k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2237
2238
134k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2239
105k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2240
105k
      } else {
2241
29.7k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2242
29.7k
      }
2243
2244
134k
      if (rv != 0) {
2245
0
        goto fail;
2246
0
      }
2247
2248
134k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2249
134k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2250
2251
134k
      return (nghttp2_ssize)(in - first);
2252
1.18M
    }
2253
1.18M
  }
2254
2255
516k
  assert(in == last);
2256
2257
126k
  DEBUGF("inflatehd: all input bytes were processed\n");
2258
2259
126k
  if (in_final) {
2260
123k
    DEBUGF("inflatehd: in_final set\n");
2261
2262
123k
    if (inflater->state != NGHTTP2_HD_STATE_OPCODE &&
2263
15.3k
        inflater->state != NGHTTP2_HD_STATE_INFLATE_START) {
2264
17
      DEBUGF("inflatehd: unacceptable state=%d\n", inflater->state);
2265
17
      rv = NGHTTP2_ERR_HEADER_COMP;
2266
2267
17
      goto fail;
2268
17
    }
2269
123k
    *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
2270
123k
  }
2271
126k
  return (nghttp2_ssize)(in - first);
2272
2273
1.63k
almost_ok:
2274
1.63k
  if (in_final) {
2275
15
    DEBUGF("inflatehd: input ended prematurely\n");
2276
2277
15
    rv = NGHTTP2_ERR_HEADER_COMP;
2278
2279
15
    goto fail;
2280
15
  }
2281
1.62k
  return (nghttp2_ssize)(in - first);
2282
2283
1.22k
fail:
2284
1.22k
  DEBUGF("inflatehd: error return %td\n", rv);
2285
2286
1.22k
  inflater->ctx.bad = 1;
2287
1.22k
  return rv;
2288
1.63k
}
2289
2290
123k
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
2291
123k
  hd_inflate_keep_free(inflater);
2292
123k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
2293
123k
  return 0;
2294
123k
}
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
}