varnish-cache/bin/varnishd/hpack/vhp_decode.c
0
/*-
1
 * Copyright (c) 2016 Varnish Software AS
2
 * All rights reserved.
3
 *
4
 * Author: Martin Blix Grydeland <martin@varnish-software.com>
5
 * Author: Dridi Boukelmoune <dridi.boukelmoune@gmail.com>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 */
31
32
#include "config.h"
33 43650
34 41050
#include <stdio.h>
35 22600
#include <string.h>
36 44825
#include <limits.h>
37 0
#include <stdlib.h>
38 17425
39 43700
#include "vdef.h"
40 350
#include "vas.h"
41 2075
#include "miniobj.h"
42 14475
43 26550
#include "hpack/vhp.h"
44 44725
45 16450
#include "vhp_hufdec.h"
46 0
47
struct vhd_ctx {
48
        struct vhd_decode *d;
49
        struct vht_table *tbl;
50
        const uint8_t *in;
51
        const uint8_t *in_e;
52
        char *out;
53
        char *out_e;
54
};
55
56
typedef enum vhd_ret_e vhd_state_f(struct vhd_ctx *ctx, unsigned first);
57
58
/* Function flags */
59
#define VHD_INCREMENTAL (1U << 0)
60
61
/* Functions */
62
enum vhd_func_e {
63
#define VHD_FSM_FUNC(NAME, func)                \
64
        VHD_F_##NAME,
65
#include "tbl/vhd_fsm_funcs.h"
66
        VHD_F__MAX,
67
};
68
#define VHD_FSM_FUNC(NAME, func)                \
69
        static vhd_state_f func;
70
#include "tbl/vhd_fsm_funcs.h"
71
72
/* States */
73
enum vhd_state_e {
74
        VHD_S__MIN = -1,
75
#define VHD_FSM(STATE, FUNC, arg1, arg2)        \
76
        VHD_S_##STATE,
77
#include "tbl/vhd_fsm.h"
78
        VHD_S__MAX,
79
};
80
static const struct vhd_state {
81
        const char              *name;
82
        enum vhd_func_e         func;
83
        unsigned                arg1;
84
        unsigned                arg2;
85
} vhd_states[VHD_S__MAX] = {
86
#define VHD_FSM(STATE, FUNC, arg1, arg2)        \
87
        [VHD_S_##STATE] = { #STATE, VHD_F_##FUNC, arg1, arg2 },
88
#include "tbl/vhd_fsm.h"
89
};
90
91
/* Utility functions */
92
static void
93 242575
vhd_set_state(struct vhd_decode *d, enum vhd_state_e state)
94
{
95 242575
        AN(d);
96 242575
        assert(state > VHD_S__MIN && state < VHD_S__MAX);
97 242575
        d->state = state;
98 242575
        d->first = 1;
99 242575
}
100
101
static void
102 169950
vhd_next_state(struct vhd_decode *d)
103
{
104 169950
        AN(d);
105 169950
        assert(d->state + 1 < VHD_S__MAX);
106 169950
        vhd_set_state(d, d->state + 1);
107 169950
}
108
109
/* State functions */
110
static enum vhd_ret_e v_matchproto_(vhd_state_f)
111 43650
vhd_skip(struct vhd_ctx *ctx, unsigned first)
112
{
113 43650
        AN(ctx);
114 43650
        AN(first);
115 43650
        vhd_next_state(ctx->d);
116 43650
        return (VHD_AGAIN);
117
}
118
119
static enum vhd_ret_e v_matchproto_(vhd_state_f)
120 40950
vhd_goto(struct vhd_ctx *ctx, unsigned first)
121
{
122
        const struct vhd_state *s;
123
124 40950
        AN(ctx);
125 40950
        AN(first);
126 40950
        assert(ctx->d->state < VHD_S__MAX);
127 40950
        s = &vhd_states[ctx->d->state];
128 40950
        assert(s->arg1 < VHD_S__MAX);
129 40950
        vhd_set_state(ctx->d, s->arg1);
130 40950
        return (VHD_AGAIN);
131
}
132
133
static enum vhd_ret_e v_matchproto_(vhd_state_f)
134 22600
vhd_idle(struct vhd_ctx *ctx, unsigned first)
135
{
136
        uint8_t c;
137
138 22600
        AN(ctx);
139 22600
        (void)first;
140
141 22600
        while (ctx->in < ctx->in_e) {
142 17475
                c = *ctx->in;
143 17475
                if ((c & 0x80) == 0x80)
144 3750
                        vhd_set_state(ctx->d, VHD_S_HP61_START);
145 13725
                else if ((c & 0xc0) == 0x40)
146 2400
                        vhd_set_state(ctx->d, VHD_S_HP621_START);
147 11325
                else if ((c & 0xf0) == 0x00)
148 11200
                        vhd_set_state(ctx->d, VHD_S_HP622_START);
149 125
                else if ((c & 0xf0) == 0x10)
150 125
                        vhd_set_state(ctx->d, VHD_S_HP623_START);
151 0
                else if ((c & 0xe0) == 0x20)
152 0
                        vhd_set_state(ctx->d, VHD_S_HP63_START);
153
                else
154 0
                        return (VHD_ERR_ARG);
155 17475
                return (VHD_AGAIN);
156
        }
157
158 5125
        return (VHD_OK);
159 22600
}
160
161
static enum vhd_ret_e v_matchproto_(vhd_state_f)
162 44825
vhd_integer(struct vhd_ctx *ctx, unsigned first)
163
{
164
        const struct vhd_state *s;
165
        struct vhd_int *i;
166
        uint8_t c;
167
        unsigned mask;
168
169 44825
        assert(UINT_MAX >= UINT32_MAX);
170
171 44825
        AN(ctx);
172 44825
        assert(ctx->d->state < VHD_S__MAX);
173 44825
        s = &vhd_states[ctx->d->state];
174 44825
        i = ctx->d->integer;
175
176 44825
        if (first) {
177 44225
                INIT_OBJ(i, VHD_INT_MAGIC);
178 44225
                i->pfx = s->arg1;
179 44225
                assert(i->pfx >= 4 && i->pfx <= 7);
180 44225
        }
181 44825
        CHECK_OBJ_NOTNULL(i, VHD_INT_MAGIC);
182
183 46300
        while (ctx->in < ctx->in_e) {
184 45700
                c = *ctx->in;
185 45700
                ctx->in++;
186 45700
                if (i->pfx) {
187 44225
                        mask = (1U << i->pfx) - 1;
188 44225
                        i->pfx = 0;
189 44225
                        i->v = c & mask;
190 44225
                        if (i->v < mask) {
191 43850
                                vhd_next_state(ctx->d);
192 43850
                                return (VHD_AGAIN);
193
                        }
194 375
                } else {
195 1475
                        if ((i->m == 28 && (c & 0x78)) || i->m > 28)
196 150
                                return (VHD_ERR_INT);
197 1325
                        i->v += (c & 0x7f) * ((uint32_t)1 << i->m);
198 1325
                        i->m += 7;
199 1325
                        if (!(c & 0x80)) {
200 225
                                vhd_next_state(ctx->d);
201 225
                                return (VHD_AGAIN);
202
                        }
203
                }
204
        }
205 600
        return (VHD_MORE);
206 44825
}
207
208
static enum vhd_ret_e v_matchproto_(vhd_state_f)
209 0
vhd_set_max(struct vhd_ctx *ctx, unsigned first)
210
{
211 0
        AN(ctx);
212 0
        AN(first);
213 0
        CHECK_OBJ_NOTNULL(ctx->d->integer, VHD_INT_MAGIC);
214 0
        if (ctx->tbl == NULL)
215 0
                return (VHD_ERR_UPD);
216 0
        if (VHT_SetMaxTableSize(ctx->tbl, ctx->d->integer->v))
217 0
                return (VHD_ERR_UPD);
218 0
        vhd_next_state(ctx->d);
219 0
        return (VHD_AGAIN);
220 0
}
221
222
static enum vhd_ret_e v_matchproto_(vhd_state_f)
223 17425
vhd_set_idx(struct vhd_ctx *ctx, unsigned first)
224
{
225 17425
        AN(ctx);
226 17425
        AN(first);
227 17425
        CHECK_OBJ_NOTNULL(ctx->d->integer, VHD_INT_MAGIC);
228 17425
        ctx->d->index = ctx->d->integer->v;
229 17425
        vhd_next_state(ctx->d);
230 17425
        return (VHD_AGAIN);
231
}
232
233
static enum vhd_ret_e v_matchproto_(vhd_state_f)
234 43700
vhd_lookup(struct vhd_ctx *ctx, unsigned first)
235
{
236
        const struct vhd_state *s;
237
        struct vhd_lookup *lu;
238
        const char *p;
239
        size_t l;
240
241 43700
        AN(ctx);
242 43700
        assert(ctx->d->state < VHD_S__MAX);
243 43700
        s = &vhd_states[ctx->d->state];
244 43700
        lu = ctx->d->lookup;
245
246 43700
        if (first)
247 9600
                INIT_OBJ(lu, VHD_LOOKUP_MAGIC);
248 43700
        CHECK_OBJ_NOTNULL(lu, VHD_LOOKUP_MAGIC);
249
250 43700
        switch (s->arg1) {
251
        case VHD_NAME:
252
        case VHD_NAME_SEC:
253 25900
                p = VHT_LookupName(ctx->tbl, ctx->d->index, &l);
254 25900
                break;
255
        case VHD_VALUE:
256
        case VHD_VALUE_SEC:
257 17800
                p = VHT_LookupValue(ctx->tbl, ctx->d->index, &l);
258 17800
                break;
259
        default:
260 0
                WRONG("vhd_lookup wrong arg1");
261 0
                break;
262
        }
263 43700
        if (first && p == NULL)
264 0
                return (VHD_ERR_IDX);
265 43700
        AN(p);
266 43700
        assert(l <= UINT_MAX);
267 43700
        if (first)
268 9600
                lu->l = l;
269
270 43700
        assert(lu->l <= l);
271 43700
        p += l - lu->l;
272 43700
        l = vmin_t(size_t, lu->l, ctx->out_e - ctx->out);
273 43700
        memcpy(ctx->out, p, l);
274 43700
        ctx->out += l;
275 43700
        lu->l -= l;
276
277 43700
        if (lu->l == 0) {
278 9600
                vhd_next_state(ctx->d);
279 9600
                return (s->arg1);
280
        }
281 34100
        assert(ctx->out == ctx->out_e);
282 34100
        return (VHD_BUF);
283 43700
}
284
285
static enum vhd_ret_e v_matchproto_(vhd_state_f)
286 325
vhd_new(struct vhd_ctx *ctx, unsigned first)
287
{
288 325
        AN(ctx);
289 325
        AN(first);
290 325
        if (ctx->tbl != NULL)
291 225
                VHT_NewEntry(ctx->tbl);
292 325
        vhd_next_state(ctx->d);
293 325
        return (VHD_AGAIN);
294
}
295
296
static enum vhd_ret_e v_matchproto_(vhd_state_f)
297 2075
vhd_new_idx(struct vhd_ctx *ctx, unsigned first)
298
{
299 2075
        AN(ctx);
300 2075
        AN(first);
301 2075
        if (ctx->tbl != NULL) {
302 2075
                if (VHT_NewEntry_Indexed(ctx->tbl, ctx->d->index))
303 0
                        return (VHD_ERR_IDX);
304 2075
        }
305 2075
        vhd_next_state(ctx->d);
306 2075
        return (VHD_AGAIN);
307 2075
}
308
309
static enum vhd_ret_e v_matchproto_(vhd_state_f)
310 13725
vhd_branch_zidx(struct vhd_ctx *ctx, unsigned first)
311
{
312
        const struct vhd_state *s;
313
314 13725
        AN(ctx);
315 13725
        (void)first;
316 13725
        assert(ctx->d->state < VHD_S__MAX);
317 13725
        s = &vhd_states[ctx->d->state];
318 13725
        assert(s->arg1 < VHD_S__MAX);
319
320 13725
        if (ctx->d->index == 0)
321 11525
                vhd_set_state(ctx->d, s->arg1);
322
        else
323 2200
                vhd_next_state(ctx->d);
324 13725
        return (VHD_AGAIN);
325
}
326
327
static enum vhd_ret_e v_matchproto_(vhd_state_f)
328 26550
vhd_branch_bit0(struct vhd_ctx *ctx, unsigned first)
329
{
330
        const struct vhd_state *s;
331
332 26550
        AN(ctx);
333 26550
        (void)first;
334 26550
        assert(ctx->d->state < VHD_S__MAX);
335 26550
        s = &vhd_states[ctx->d->state];
336 26550
        assert(s->arg1 < VHD_S__MAX);
337
338 26550
        if (ctx->in == ctx->in_e)
339 200
                return (VHD_MORE);
340
341 26350
        if (*ctx->in & 0x80)
342 1675
                vhd_set_state(ctx->d, s->arg1);
343
        else
344 24675
                vhd_next_state(ctx->d);
345 26350
        return (VHD_AGAIN);
346 26550
}
347
348
static enum vhd_ret_e v_matchproto_(vhd_state_f)
349 44725
vhd_raw(struct vhd_ctx *ctx, unsigned first)
350
{
351
        const struct vhd_state *s;
352
        struct vhd_raw *raw;
353
        size_t l2;
354
355 44725
        AN(ctx);
356 44725
        assert(ctx->d->state < VHD_S__MAX);
357 44725
        s = &vhd_states[ctx->d->state];
358
359 44725
        raw = ctx->d->raw;
360 44725
        if (first) {
361 24675
                CHECK_OBJ_NOTNULL(ctx->d->integer, VHD_INT_MAGIC);
362 24675
                l2 = ctx->d->integer->v;
363 24675
                INIT_OBJ(raw, VHD_RAW_MAGIC);
364 24675
                raw->l = l2;
365 24675
        }
366 44725
        CHECK_OBJ_NOTNULL(raw, VHD_RAW_MAGIC);
367
368 88025
        while (raw->l > 0) {
369 63475
                l2 = raw->l;
370 63475
                if (l2 > (ctx->in_e - ctx->in))
371 26500
                        l2 = ctx->in_e - ctx->in;
372 63475
                if (l2 == 0)
373 13875
                        return (VHD_MORE);
374 49600
                if (l2 > (ctx->out_e - ctx->out))
375 12600
                        l2 = ctx->out_e - ctx->out;
376 49600
                if (l2 == 0)
377 6300
                        return (VHD_BUF);
378 43300
                memcpy(ctx->out, ctx->in, l2);
379 43300
                ctx->in += l2;
380 43300
                if (ctx->tbl != NULL && (s->arg2 & VHD_INCREMENTAL)) {
381 15275
                        switch (s->arg1) {
382
                        case VHD_NAME:
383 775
                                VHT_AppendName(ctx->tbl, ctx->out, l2);
384 775
                                break;
385
                        case VHD_VALUE:
386 14500
                                VHT_AppendValue(ctx->tbl, ctx->out, l2);
387 14500
                                break;
388
                        default:
389 0
                                WRONG("vhd_raw wrong arg1");
390 0
                                break;
391
                        }
392 15275
                }
393 43300
                ctx->out += l2;
394 43300
                raw->l -= l2;
395
        }
396 24550
        vhd_next_state(ctx->d);
397 24550
        return (s->arg1);
398 44725
}
399
400
static enum vhd_ret_e v_matchproto_(vhd_state_f)
401 16450
vhd_huffman(struct vhd_ctx *ctx, unsigned first)
402
{
403
        const struct vhd_state *s;
404
        struct vhd_huffman *huf;
405
        enum vhd_ret_e r;
406
        unsigned u, l;
407
408 16450
        AN(ctx);
409 16450
        assert(ctx->d->state < VHD_S__MAX);
410 16450
        s = &vhd_states[ctx->d->state];
411
412 16450
        huf = ctx->d->huffman;
413 16450
        if (first) {
414 1675
                CHECK_OBJ_NOTNULL(ctx->d->integer, VHD_INT_MAGIC);
415 1675
                l = ctx->d->integer->v;
416 1675
                INIT_OBJ(huf, VHD_HUFFMAN_MAGIC);
417 1675
                huf->len = l;
418 1675
        }
419 16450
        CHECK_OBJ_NOTNULL(huf, VHD_HUFFMAN_MAGIC);
420
421 16450
        r = VHD_OK;
422 16450
        l = 0;
423 39450
        while (1) {
424 39450
                assert(huf->pos < HUFDEC_LEN);
425 39450
                assert(hufdec[huf->pos].mask > 0);
426 39450
                assert(hufdec[huf->pos].mask <= 8);
427
428 39450
                if (huf->len > 0 && huf->blen < hufdec[huf->pos].mask) {
429
                        /* Refill from input */
430 23375
                        if (ctx->in == ctx->in_e) {
431 5700
                                r = VHD_MORE;
432 5700
                                break;
433
                        }
434 17675
                        huf->bits = (huf->bits << 8) | *ctx->in;
435 17675
                        huf->blen += 8;
436 17675
                        huf->len--;
437 17675
                        ctx->in++;
438 17675
                }
439
440 33750
                if (huf->len == 0 && huf->pos == 0 && huf->blen <= 7 &&
441 2125
                    huf->bits == (1U << huf->blen) - 1U) {
442
                        /* End of stream */
443 1375
                        r = s->arg1;
444 1375
                        vhd_next_state(ctx->d);
445 1375
                        break;
446
                }
447
448 32375
                if (ctx->out + l == ctx->out_e) {
449 9175
                        r = VHD_BUF;
450 9175
                        break;
451
                }
452
453 23200
                if (huf->blen >= hufdec[huf->pos].mask)
454 22600
                        u = huf->bits >> (huf->blen - hufdec[huf->pos].mask);
455
                else
456 600
                        u = huf->bits << (hufdec[huf->pos].mask - huf->blen);
457 23200
                huf->pos += u;
458 23200
                assert(huf->pos < HUFDEC_LEN);
459
460 23200
                if (hufdec[huf->pos].len == 0 ||
461 23100
                    hufdec[huf->pos].len > huf->blen) {
462
                        /* Invalid or incomplete code */
463 200
                        r = VHD_ERR_HUF;
464 200
                        break;
465
                }
466
467 23000
                huf->blen -= hufdec[huf->pos].len;
468 23000
                huf->bits &= (1U << huf->blen) - 1U;
469
470 23000
                if (hufdec[huf->pos].jump) {
471 900
                        huf->pos += hufdec[huf->pos].jump;
472 900
                        assert(huf->pos < HUFDEC_LEN);
473 900
                } else {
474 22100
                        ctx->out[l++] = hufdec[huf->pos].chr;
475 22100
                        huf->pos = 0;
476
                }
477
        }
478
479 16450
        if (l > 0 && ctx->tbl != NULL && (s->arg2 & VHD_INCREMENTAL)) {
480 14175
                switch (s->arg1) {
481
                case VHD_NAME:
482 750
                        VHT_AppendName(ctx->tbl, ctx->out, l);
483 750
                        break;
484
                case VHD_VALUE:
485 13425
                        VHT_AppendValue(ctx->tbl, ctx->out, l);
486 13425
                        break;
487
                default:
488 0
                        WRONG("vhd_raw wrong arg1");
489 0
                        break;
490
                }
491 14175
        }
492 16450
        ctx->out += l;
493
494 16450
        assert(r != VHD_OK);
495 16450
        return (r);
496
}
497
498
/* Public interface */
499
500
const char *
501 875
VHD_Error(enum vhd_ret_e r)
502
{
503 875
        switch (r) {
504
#define VHD_RET(NAME, VAL, DESC)                        \
505
        case VHD_##NAME:                                \
506
                return ("VHD_" #NAME " (" DESC ")");
507
#include "tbl/vhd_return.h"
508
        default:
509 0
                return ("VHD_UNKNOWN");
510
        }
511 875
}
512
513
enum vhd_ret_e
514 110950
VHD_Decode(struct vhd_decode *d, struct vht_table *tbl,
515
    const uint8_t *in, size_t inlen, size_t *p_inused,
516
    char *out, size_t outlen, size_t *p_outused)
517
{
518
        const struct vhd_state *s;
519
        struct vhd_ctx ctx[1];
520
        enum vhd_ret_e ret;
521
        unsigned first;
522
523 110950
        CHECK_OBJ_NOTNULL(d, VHD_DECODE_MAGIC);
524 110950
        CHECK_OBJ_ORNULL(tbl, VHT_TABLE_MAGIC);
525 110950
        AN(in);
526 110950
        AN(p_inused);
527 110950
        AN(out);
528 110950
        AN(p_outused);
529
530 110950
        if (d->error < 0)
531 0
                return (d->error);
532
533 110950
        assert(*p_inused <= inlen);
534 110950
        assert(*p_outused <= outlen);
535
536 110950
        ctx->d = d;
537 110950
        ctx->tbl = tbl;
538 110950
        ctx->in = in + *p_inused;
539 110950
        ctx->in_e = in + inlen;
540 110950
        ctx->out = out + *p_outused;
541 110950
        ctx->out_e = out + outlen;
542
543 110950
        do {
544 317000
                first = d->first;
545 317000
                d->first = 0;
546 317000
                assert(d->state < VHD_S__MAX);
547 317000
                s = &vhd_states[d->state];
548 317000
                switch (s->func) {
549
#define VHD_FSM_FUNC(NAME, func)                \
550
                case VHD_F_##NAME:              \
551
                        ret = func(ctx, first); \
552
                        break;
553
#include "tbl/vhd_fsm_funcs.h"
554
                default:
555 0
                        WRONG("Undefined vhd function");
556 0
                        break;
557
                }
558 317000
        } while (ret == VHD_AGAIN);
559
560 110950
        if (ret < 0)
561 350
                d->error = ret;
562
563 110950
        assert(in + *p_inused <= ctx->in);
564 110950
        *p_inused += ctx->in - (in + *p_inused);
565 110950
        assert(out + *p_outused <= ctx->out);
566 110950
        *p_outused += ctx->out - (out + *p_outused);
567
568 110950
        return (ret);
569 110950
}
570
571
void
572 5300
VHD_Init(struct vhd_decode *d)
573
{
574
575 5300
        AN(d);
576 5300
        assert(VHD_S__MAX <= UINT16_MAX);
577 5300
        assert(HUFDEC_LEN <= UINT16_MAX);
578 5300
        INIT_OBJ(d, VHD_DECODE_MAGIC);
579 5300
        d->state = VHD_S_IDLE;
580 5300
        d->first = 1;
581 5300
}
582
583
/* Test driver */
584
585
#ifdef DECODE_TEST_DRIVER
586
587
#include <ctype.h>
588
#include <stdarg.h>
589
590
static int verbose = 0;
591
592
static size_t
593 2600
hexbuf(uint8_t *buf, size_t buflen, const char *h)
594
{
595
        size_t l;
596
        uint8_t u;
597
598 2600
        AN(h);
599 2600
        AN(buf);
600
601 2600
        l = 0;
602 139900
        for (; *h != '\0'; h++) {
603 137300
                if (l == buflen * 2)
604 0
                        WRONG("Too small buffer");
605 137300
                if (isspace(*h))
606 24900
                        continue;
607 112400
                if (*h >= '0' && *h <= '9')
608 84500
                        u = *h - '0';
609 27900
                else if (*h >= 'a' && *h <= 'f')
610 27900
                        u = 0xa + *h - 'a';
611 0
                else if (*h >= 'A' && *h <= 'F')
612 0
                        u = 0xa + *h - 'A';
613
                else
614 0
                        WRONG("Bad input character");
615 112400
                assert(u <= 0xf);
616 112400
                if (l % 2 == 0) {
617 56200
                        u <<= 4;
618 56200
                        buf[l / 2] = u;
619 56200
                } else {
620 56200
                        buf[l / 2] |= u;
621
                }
622 112400
                l++;
623 112400
        }
624 2600
        AZ(l % 2);
625 2600
        return (l / 2);
626
}
627
628
static int
629 1800
match(const char *b, size_t l, ...)
630
{
631
        va_list ap;
632
        const char *e;
633
        const char *m;
634 1800
        int r = 0;
635
636 1800
        va_start(ap, l);
637 1800
        e = b + l;
638 14200
        while (1) {
639 14200
                m = va_arg(ap, const char *);
640 14200
                if (m == NULL)
641 1800
                        break;
642 12400
                l = strlen(m);
643 12400
                if (e - b <= l || b[l] != '\0' || strncmp(b, m, l)) {
644 0
                        printf("%.*s != %s\n", (int)(e - b), b, m);
645 0
                        r = -1;
646 0
                        break;
647 12400
                } else if (verbose) {
648 0
                        printf("%s == %s\n", b, m);
649 0
                }
650 12400
                b += l + 1;
651
        }
652 1800
        va_end(ap);
653 1800
        return (r);
654
}
655
656
#define M_1IN (1U << 0)
657
#define M_1OUT (1U << 1)
658
659
static enum vhd_ret_e
660 2600
decode(struct vhd_decode *d, struct vht_table *tbl, uint8_t *in, size_t in_l,
661
    char *out, size_t out_l, unsigned m)
662
{
663
        size_t in_u, out_u;
664
        enum vhd_ret_e r;
665
666 2600
        CHECK_OBJ_NOTNULL(d, VHD_DECODE_MAGIC);
667 2600
        AN(in);
668 2600
        AN(out);
669
670 2600
        in_u = 0;
671 2600
        out_u = 0;
672
673 85025
        while (1) {
674 170050
                r = VHD_Decode(d, tbl, in,
675 85025
                    (m & M_1IN ? (in_l > in_u ? in_u + 1 : in_u) : in_l),
676
                    &in_u,
677 85025
                    out,
678 85025
                    (m & M_1OUT ? (out_l > out_u ? out_u + 1 : out_u) : out_l),
679
                    &out_u);
680 85025
                assert(in_u <= in_l);
681 85025
                assert(out_u <= out_l);
682 85025
                if (r < VHD_OK)
683 300
                        return (r);
684
685 84725
                switch (r) {
686
                case VHD_OK:
687 2100
                        return (r);
688
689
                case VHD_MORE:
690 20350
                        if (in_u == in_l)
691 200
                                return (r);
692 20150
                        break;
693
694
                case VHD_BUF:
695 49575
                        if (out_u == out_l)
696 0
                                return (r);
697 49575
                        break;
698
699
                case VHD_NAME:
700
                case VHD_NAME_SEC:
701 6500
                        assert(out_l - out_u > 0);
702 6500
                        out[out_u++] = '\0';
703 6500
                        if (verbose)
704 0
                                printf("Name%s: '%s'\n",
705 0
                                    (r == VHD_NAME_SEC ? " (sec)" : ""),
706 0
                                    out);
707 6500
                        out += out_u;
708 6500
                        out_l -= out_u;
709 6500
                        out_u = 0;
710 6500
                        break;
711
712
                case VHD_VALUE:
713
                case VHD_VALUE_SEC:
714 6200
                        assert(out_l - out_u > 0);
715 6200
                        out[out_u++] = '\0';
716 6200
                        if (verbose)
717 0
                                printf("Value%s: '%s'\n",
718 0
                                    (r == VHD_VALUE_SEC ? " (sec)" : ""),
719 0
                                    out);
720 6200
                        out += out_u;
721 6200
                        out_l -= out_u;
722 6200
                        out_u = 0;
723 6200
                        break;
724
725
                default:
726 0
                        WRONG("Wrong return code");
727 0
                        break;
728
                }
729
        }
730
731
        NEEDLESS(return (VHD_OK));
732 2600
}
733
734
#define CHECK_RET(r, e)                                 \
735
        do {                                            \
736
                if (verbose || r != e) {                \
737
                        printf("%s %s %s\n",            \
738
                            VHD_Error(r),               \
739
                            (r == e ? "==" : "!="),     \
740
                            VHD_Error(e));              \
741
                }                                       \
742
                assert(r == e);                         \
743
        } while (0)
744
745
#define CHECK_INT(d, u)                                                 \
746
        do {                                                            \
747
                CHECK_OBJ_NOTNULL(d->integer, VHD_INT_MAGIC);           \
748
                if (verbose || d->integer->v != u) {                    \
749
                        printf("%u %s %u\n", d->integer->v,             \
750
                            (d->integer->v == u ? "==" : "!="),         \
751
                            u);                                         \
752
                }                                                       \
753
                assert(d->integer->v == u);                             \
754
        } while (0)
755
756
static void
757 100
test_integer(unsigned mode)
758
{
759
        struct vhd_decode d[1];
760
        uint8_t in[128];
761
        size_t in_l;
762
        char out[128];
763
        enum vhd_ret_e r;
764
765
        /* Test single byte decoding */
766 100
        VHD_Init(d);
767 100
        vhd_set_state(d, VHD_S_TEST_INT5);
768 100
        in_l = hexbuf(in, sizeof in, "1e");
769 100
        r = decode(d, NULL, in, in_l, out, sizeof out, mode);
770 100
        CHECK_RET(r, VHD_OK);
771 100
        CHECK_INT(d, 30);
772
773
        /* Test multibyte decoding */
774 100
        VHD_Init(d);
775 100
        vhd_set_state(d, VHD_S_TEST_INT5);
776 100
        in_l = hexbuf(in, sizeof in, "ff 9a 0a");
777 100
        r = decode(d, NULL, in, in_l, out, sizeof out, mode);
778 100
        CHECK_RET(r, VHD_OK);
779 100
        CHECK_INT(d, 1337);
780
781
        /* Test max size we allow */
782 100
        VHD_Init(d);
783 100
        vhd_set_state(d, VHD_S_TEST_INT5);
784 100
        in_l = hexbuf(in, sizeof in, "1f ff ff ff ff 07");
785 100
        r = decode(d, NULL, in, in_l, out, sizeof out, mode);
786 100
        CHECK_RET(r, VHD_OK);
787 100
        CHECK_INT(d, 0x8000001E);
788
789
        /* Test overflow */
790 100
        VHD_Init(d);
791 100
        vhd_set_state(d, VHD_S_TEST_INT5);
792 100
        in_l = hexbuf(in, sizeof in, "1f ff ff ff ff 08");
793 100
        r = decode(d, NULL, in, in_l, out, sizeof out, mode);
794 100
        CHECK_RET(r, VHD_ERR_INT);
795 100
}
796
797
static void
798 100
test_raw(unsigned mode)
799
{
800
        struct vhd_decode d[1];
801
        uint8_t in[128];
802
        size_t in_l;
803
        char out[128];
804
        enum vhd_ret_e r;
805
806
        /* Test raw encoding */
807 100
        VHD_Init(d);
808 100
        vhd_set_state(d, VHD_S_TEST_LITERAL);
809 100
        in_l = hexbuf(in, sizeof in,
810
            "0a63 7573 746f 6d2d 6b65 790d 6375 7374 6f6d 2d68 6561 6465 72");
811 100
        r = decode(d, NULL, in, in_l, out, sizeof out, mode);
812 100
        CHECK_RET(r, VHD_OK);
813 100
        AZ(match(out, sizeof out, "custom-key", "custom-header", NULL));
814
815
        /* Test too short input */
816 100
        VHD_Init(d);
817 100
        vhd_set_state(d, VHD_S_TEST_LITERAL);
818 100
        in_l = hexbuf(in, sizeof in,
819
            "02");
820 100
        r = decode(d, NULL, in, in_l, out, sizeof out, mode);
821 100
        CHECK_RET(r, VHD_MORE);
822 100
}
823
824
static void
825 100
test_huffman(unsigned mode)
826
{
827
        struct vhd_decode d[1];
828
        uint8_t in[256];
829
        size_t in_l;
830
        char out[256];
831
        enum vhd_ret_e r;
832
833
        /* Decode a huffman encoded value */
834 100
        VHD_Init(d);
835 100
        in_l = hexbuf(in, sizeof in,
836
            "0141 8cf1 e3c2 e5f2 3a6b a0ab 90f4 ff");
837 100
        vhd_set_state(d, VHD_S_TEST_LITERAL);
838 100
        r = decode(d, NULL, in, in_l, out, sizeof out, mode);
839 100
        CHECK_RET(r, VHD_OK);
840 100
        AZ(match(out, sizeof out, "A", "www.example.com", NULL));
841
842
        /* Decode an incomplete input buffer */
843 100
        VHD_Init(d);
844 100
        in_l = hexbuf(in, sizeof in,
845
            "0141 81");
846 100
        vhd_set_state(d, VHD_S_TEST_LITERAL);
847 100
        r = decode(d, NULL, in, in_l, out, sizeof out, mode);
848 100
        CHECK_RET(r, VHD_MORE);
849
850
        /* Decode an incomplete huffman code */
851 100
        VHD_Init(d);
852 100
        in_l = hexbuf(in, sizeof in,
853
            "0141 81 fe");
854 100
        vhd_set_state(d, VHD_S_TEST_LITERAL);
855 100
        r = decode(d, NULL, in, in_l, out, sizeof out, mode);
856 100
        CHECK_RET(r, VHD_ERR_HUF);
857
858
        /* Decode an invalid huffman code */
859 100
        VHD_Init(d);
860 100
        in_l = hexbuf(in, sizeof in,
861
            "0141 84 ff ff ff ff");
862 100
        vhd_set_state(d, VHD_S_TEST_LITERAL);
863 100
        r = decode(d, NULL, in, in_l, out, sizeof out, mode);
864 100
        CHECK_RET(r, VHD_ERR_HUF);
865 100
}
866
867
static void
868 100
test_c2(unsigned mode)
869
{
870
        struct vhd_decode d[1];
871
        uint8_t in[256];
872
        size_t in_l;
873
        char out[256];
874
        enum vhd_ret_e r;
875
876
        /* See RFC 7541 Appendix C.2 */
877
878 100
        VHD_Init(d);
879
880
        /* C.2.1 */
881 100
        in_l = hexbuf(in, sizeof in,
882
            "400a 6375 7374 6f6d 2d6b 6579 0d63 7573"
883
            "746f 6d2d 6865 6164 6572");
884 100
        r = decode(d, NULL, in, in_l, out, sizeof out, mode);
885 100
        CHECK_RET(r, VHD_OK);
886 100
        AZ(match(out, sizeof out,
887
                "custom-key", "custom-header",
888
                NULL));
889
890
        /* C.2.2 */
891 100
        in_l = hexbuf(in, sizeof in,
892
            "040c 2f73 616d 706c 652f 7061 7468");
893 100
        r = decode(d, NULL, in, in_l, out, sizeof out, mode);
894 100
        CHECK_RET(r, VHD_OK);
895 100
        AZ(match(out, sizeof out,
896
                ":path", "/sample/path",
897
                NULL));
898
899
        /* C.2.3 */
900 100
        in_l = hexbuf(in, sizeof in,
901
            "1008 7061 7373 776f 7264 0673 6563 7265"
902
            "74");
903 100
        r = decode(d, NULL, in, in_l, out, sizeof out, mode);
904 100
        CHECK_RET(r, VHD_OK);
905 100
        AZ(match(out, sizeof out,
906
                "password", "secret",
907
                NULL));
908
909
        /* C.2.4 */
910 100
        in_l = hexbuf(in, sizeof in,
911
            "82");
912 100
        r = decode(d, NULL, in, in_l, out, sizeof out, mode);
913 100
        CHECK_RET(r, VHD_OK);
914 100
        AZ(match(out, sizeof out,
915
                ":method", "GET",
916
                NULL));
917 100
}
918
919
static void
920 100
test_c3(unsigned mode)
921
{
922
        struct vht_table t[1];
923
        struct vhd_decode d[1];
924
        uint8_t in[256];
925
        size_t in_l;
926
        char out[256];
927
        enum vhd_ret_e r;
928
929
        /* See RFC 7541 Appendix C.3 */
930
931 100
        AZ(VHT_Init(t, 4096));
932 100
        VHD_Init(d);
933
934
        /* C.3.1 */
935 100
        in_l = hexbuf(in, sizeof in,
936
            "8286 8441 0f77 7777 2e65 7861 6d70 6c65"
937
            "2e63 6f6d");
938 100
        r = decode(d, t, in, in_l, out, sizeof out, mode);
939 100
        CHECK_RET(r, VHD_OK);
940 100
        AZ(match(out, sizeof out,
941
                ":method", "GET",
942
                ":scheme", "http",
943
                ":path", "/",
944
                ":authority", "www.example.com",
945
                NULL));
946
947
        /* C.3.2 */
948 100
        in_l = hexbuf(in, sizeof in,
949
            "8286 84be 5808 6e6f 2d63 6163 6865");
950 100
        r = decode(d, t, in, in_l, out, sizeof out, mode);
951 100
        CHECK_RET(r, VHD_OK);
952 100
        AZ(match(out, sizeof out,
953
                ":method", "GET",
954
                ":scheme", "http",
955
                ":path", "/",
956
                ":authority", "www.example.com",
957
                "cache-control", "no-cache",
958
                NULL));
959
960
        /* C.3.3 */
961 100
        in_l = hexbuf(in, sizeof in,
962
            "8287 85bf 400a 6375 7374 6f6d 2d6b 6579"
963
            "0c63 7573 746f 6d2d 7661 6c75 65");
964 100
        r = decode(d, t, in, in_l, out, sizeof out, mode);
965 100
        CHECK_RET(r, VHD_OK);
966 100
        AZ(match(out, sizeof out,
967
                ":method", "GET",
968
                ":scheme", "https",
969
                ":path", "/index.html",
970
                ":authority", "www.example.com",
971
                "custom-key", "custom-value",
972
                NULL));
973
974 100
        VHT_Fini(t);
975 100
}
976
977
static void
978 100
test_c4(unsigned mode)
979
{
980
        struct vht_table t[1];
981
        struct vhd_decode d[1];
982
        uint8_t in[256];
983
        size_t in_l;
984
        char out[256];
985
        enum vhd_ret_e r;
986
987
        /* See RFC 7541 Appendix C.4 */
988
989 100
        AZ(VHT_Init(t, 4096));
990 100
        VHD_Init(d);
991
992
        /* C.4.1 */
993 100
        in_l = hexbuf(in, sizeof in,
994
            "8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4 ff");
995 100
        r = decode(d, t, in, in_l, out, sizeof out, mode);
996 100
        CHECK_RET(r, VHD_OK);
997 100
        AZ(match(out, sizeof out,
998
                ":method", "GET",
999
                ":scheme", "http",
1000
                ":path", "/",
1001
                ":authority", "www.example.com",
1002
                NULL));
1003
1004
        /* C.4.2 */
1005 100
        in_l = hexbuf(in, sizeof in,
1006
            "8286 84be 5886 a8eb 1064 9cbf");
1007 100
        r = decode(d, t, in, in_l, out, sizeof out, mode);
1008 100
        CHECK_RET(r, VHD_OK);
1009 100
        AZ(match(out, sizeof out,
1010
                ":method", "GET",
1011
                ":scheme", "http",
1012
                ":path", "/",
1013
                ":authority", "www.example.com",
1014
                "cache-control", "no-cache",
1015
                NULL));
1016
1017
        /* C.4.3 */
1018 100
        in_l = hexbuf(in, sizeof in,
1019
            "8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925"
1020
            "a849 e95b b8e8 b4bf");
1021 100
        r = decode(d, t, in, in_l, out, sizeof out, mode);
1022 100
        CHECK_RET(r, VHD_OK);
1023 100
        AZ(match(out, sizeof out,
1024
                ":method", "GET",
1025
                ":scheme", "https",
1026
                ":path", "/index.html",
1027
                ":authority", "www.example.com",
1028
                "custom-key", "custom-value",
1029
                NULL));
1030
1031 100
        VHT_Fini(t);
1032 100
}
1033
1034
static void
1035 100
test_c5(unsigned mode)
1036
{
1037
        struct vht_table t[1];
1038
        struct vhd_decode d[1];
1039
        uint8_t in[256];
1040
        size_t in_l;
1041
        char out[256];
1042
        enum vhd_ret_e r;
1043
1044
        /* See RFC 7541 Appendix C.5 */
1045
1046 100
        AZ(VHT_Init(t, 256));
1047 100
        VHD_Init(d);
1048
1049
        /* C.5.1 */
1050 100
        in_l = hexbuf(in, sizeof in,
1051
            "4803 3330 3258 0770 7269 7661 7465 611d"
1052
            "4d6f 6e2c 2032 3120 4f63 7420 3230 3133"
1053
            "2032 303a 3133 3a32 3120 474d 546e 1768"
1054
            "7474 7073 3a2f 2f77 7777 2e65 7861 6d70"
1055
            "6c65 2e63 6f6d");
1056 100
        r = decode(d, t, in, in_l, out, sizeof out, mode);
1057 100
        CHECK_RET(r, VHD_OK);
1058 100
        AZ(match(out, sizeof out,
1059
                ":status", "302",
1060
                "cache-control", "private",
1061
                "date", "Mon, 21 Oct 2013 20:13:21 GMT",
1062
                "location", "https://www.example.com",
1063
                NULL));
1064
1065
        /* C.5.2 */
1066 100
        in_l = hexbuf(in, sizeof in,
1067
            "4803 3330 37c1 c0bf");
1068 100
        r = decode(d, t, in, in_l, out, sizeof out, mode);
1069 100
        CHECK_RET(r, VHD_OK);
1070 100
        AZ(match(out, sizeof out,
1071
                ":status", "307",
1072
                "cache-control", "private",
1073
                "date", "Mon, 21 Oct 2013 20:13:21 GMT",
1074
                "location", "https://www.example.com",
1075
                NULL));
1076
1077
        /* C.5.3 */
1078 100
        in_l = hexbuf(in, sizeof in,
1079
            "88c1 611d 4d6f 6e2c 2032 3120 4f63 7420"
1080
            "3230 3133 2032 303a 3133 3a32 3220 474d"
1081
            "54c0 5a04 677a 6970 7738 666f 6f3d 4153"
1082
            "444a 4b48 514b 425a 584f 5157 454f 5049"
1083
            "5541 5851 5745 4f49 553b 206d 6178 2d61"
1084
            "6765 3d33 3630 303b 2076 6572 7369 6f6e"
1085
            "3d31");
1086 100
        r = decode(d, t, in, in_l, out, sizeof out, mode);
1087 100
        CHECK_RET(r, VHD_OK);
1088 100
        AZ(match(out, sizeof out,
1089
                ":status", "200",
1090
                "cache-control", "private",
1091
                "date", "Mon, 21 Oct 2013 20:13:22 GMT",
1092
                "location", "https://www.example.com",
1093
                "content-encoding", "gzip",
1094
                "set-cookie",
1095
                "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
1096
                NULL));
1097
1098 100
        VHT_Fini(t);
1099 100
}
1100
1101
static void
1102 100
test_c6(unsigned mode)
1103
{
1104
        struct vht_table t[1];
1105
        struct vhd_decode d[1];
1106
        uint8_t in[256];
1107
        size_t in_l;
1108
        char out[256];
1109
        enum vhd_ret_e r;
1110
1111
        /* See RFC 7541 Appendix C.6 */
1112
1113 100
        AZ(VHT_Init(t, 256));
1114 100
        VHD_Init(d);
1115
1116
        /* C.6.1 */
1117 100
        in_l = hexbuf(in, sizeof in,
1118
            "4882 6402 5885 aec3 771a 4b61 96d0 7abe"
1119
            "9410 54d4 44a8 2005 9504 0b81 66e0 82a6"
1120
            "2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8"
1121
            "e9ae 82ae 43d3");
1122 100
        r = decode(d, t, in, in_l, out, sizeof out, mode);
1123 100
        CHECK_RET(r, VHD_OK);
1124 100
        AZ(match(out, sizeof out,
1125
                ":status", "302",
1126
                "cache-control", "private",
1127
                "date", "Mon, 21 Oct 2013 20:13:21 GMT",
1128
                "location", "https://www.example.com",
1129
                NULL));
1130
1131
        /* C.6.2 */
1132 100
        in_l = hexbuf(in, sizeof in,
1133
            "4883 640e ffc1 c0bf");
1134 100
        r = decode(d, t, in, in_l, out, sizeof out, mode);
1135 100
        CHECK_RET(r, VHD_OK);
1136 100
        AZ(match(out, sizeof out,
1137
                ":status", "307",
1138
                "cache-control", "private",
1139
                "date", "Mon, 21 Oct 2013 20:13:21 GMT",
1140
                "location", "https://www.example.com",
1141
                NULL));
1142
1143
        /* C.6.3 */
1144 100
        in_l = hexbuf(in, sizeof in,
1145
            "88c1 6196 d07a be94 1054 d444 a820 0595"
1146
            "040b 8166 e084 a62d 1bff c05a 839b d9ab"
1147
            "77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b"
1148
            "3960 d5af 2708 7f36 72c1 ab27 0fb5 291f"
1149
            "9587 3160 65c0 03ed 4ee5 b106 3d50 07");
1150 100
        r = decode(d, t, in, in_l, out, sizeof out, mode);
1151 100
        CHECK_RET(r, VHD_OK);
1152 100
        AZ(match(out, sizeof out,
1153
                ":status", "200",
1154
                "cache-control", "private",
1155
                "date", "Mon, 21 Oct 2013 20:13:22 GMT",
1156
                "location", "https://www.example.com",
1157
                "content-encoding", "gzip",
1158
                "set-cookie",
1159
                "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
1160
                NULL));
1161
1162 100
        VHT_Fini(t);
1163 100
}
1164
1165
#define do_test(name)                                           \
1166
        do {                                                    \
1167
                printf("Doing test: %s\n", #name);              \
1168
                name(0);                                        \
1169
                printf("Doing test: %s 1IN\n", #name);          \
1170
                name(M_1IN);                                    \
1171
                printf("Doing test: %s 1OUT\n", #name);         \
1172
                name(M_1OUT);                                   \
1173
                printf("Doing test: %s 1IN|1OUT\n", #name);     \
1174
                name(M_1IN|M_1OUT);                             \
1175
                printf("Test finished: %s\n\n", #name);         \
1176
        } while (0)
1177
1178
int
1179 25
main(int argc, char **argv)
1180
{
1181 25
        if (argc == 2 && !strcmp(argv[1], "-v"))
1182 0
                verbose = 1;
1183 25
        else if (argc != 1) {
1184 0
                fprintf(stderr, "Usage: %s [-v]\n", argv[0]);
1185 0
                return (1);
1186
        }
1187
1188 25
        if (verbose) {
1189 0
                printf("sizeof (struct vhd_int)=%zu\n",
1190
                    sizeof (struct vhd_int));
1191 0
                printf("sizeof (struct vhd_lookup)=%zu\n",
1192
                    sizeof (struct vhd_lookup));
1193 0
                printf("sizeof (struct vhd_raw)=%zu\n",
1194
                    sizeof (struct vhd_raw));
1195 0
                printf("sizeof (struct vhd_huffman)=%zu\n",
1196
                    sizeof (struct vhd_huffman));
1197 0
                printf("sizeof (struct vhd_decode)=%zu\n",
1198
                    sizeof (struct vhd_decode));
1199 0
        }
1200
1201 25
        do_test(test_integer);
1202 25
        do_test(test_raw);
1203 25
        do_test(test_huffman);
1204
1205 25
        do_test(test_c2);
1206 25
        do_test(test_c3);
1207 25
        do_test(test_c4);
1208 25
        do_test(test_c5);
1209 25
        do_test(test_c6);
1210
1211 25
        return (0);
1212 25
}
1213
1214
#endif  /* DECODE_TEST_DRIVER */