Coverage Report

Created: 2022-10-16 06:45

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