varnish-cache/lib/libvarnishapi/vsl_query.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Martin Blix Grydeland <martin@varnish-software.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
34
#include <ctype.h>
35
#include <math.h>
36
#include <stdio.h>
37
38
#include "vdef.h"
39
#include "vas.h"
40
#include "miniobj.h"
41
42
#include "vbm.h"
43
#include "vnum.h"
44
#include "vqueue.h"
45
#include "vre.h"
46
#include "vsb.h"
47
48
#include "vapi/vsl.h"
49
50
#include "vsl_api.h"
51
#include "vxp.h"
52
53
struct vslq_query {
54
        unsigned                magic;
55
#define VSLQ_QUERY_MAGIC        0x122322A5
56
57
        struct vex              *vex;
58
};
59
60
#define VSLQ_TEST_NUMOP(TYPE, PRE_LHS, OP, PRE_RHS)             \
61
        do {                                                    \
62
                switch (TYPE) {                                 \
63
                case VEX_INT:                                   \
64
                        if (PRE_LHS##_int OP PRE_RHS##_int)     \
65
                                return (1);                     \
66
                        return (0);                             \
67
                case VEX_FLOAT:                                 \
68
                        if (PRE_LHS##_float OP PRE_RHS##_float) \
69
                                return (1);                     \
70
                        return (0);                             \
71
                default:                                        \
72
                        WRONG("Wrong RHS type");                \
73
                }                                               \
74
        } while(0)                                              \
75
76
static int
77 19750
vslq_test_vxid(const struct vex *vex, const struct VSL_transaction *trans)
78
{
79
        const struct vex_rhs *rhs;
80
81 19750
        AN(vex);
82 19750
        AN(trans);
83
84 19750
        rhs = vex->rhs;
85 19750
        CHECK_OBJ_NOTNULL(rhs, VEX_RHS_MAGIC);
86
87
        /* Prepare */
88 19750
        switch (vex->tok) {
89
        case T_EQ:              /* == */
90
        case T_NEQ:             /* != */
91
        case '<':
92
        case '>':
93
        case T_LEQ:             /* <= */
94
        case T_GEQ:             /* >= */
95 19750
                if (rhs->type != VEX_INT)
96 0
                        WRONG("Wrong RHS type for vxid");
97
                /* FALLTHROUGH */
98
        default:
99 19750
                break;
100
        }
101
102
        /* Compare */
103 19750
        switch (vex->tok) {
104
#define VXID_TEST_NUMOP(OP) return (trans->vxid OP rhs->val_int)
105 19750
        case T_EQ:      VXID_TEST_NUMOP(==);
106 0
        case T_NEQ:     VXID_TEST_NUMOP(!=);
107 0
        case '<':       VXID_TEST_NUMOP(<);
108 0
        case '>':       VXID_TEST_NUMOP(>);
109 0
        case T_LEQ:     VXID_TEST_NUMOP(<=);
110 0
        case T_GEQ:     VXID_TEST_NUMOP(>=);
111
        #undef VXID_TEST_NUMOP
112 0
        default:        WRONG("Bad vxid expression token");
113 0
        }
114
115 0
        NEEDLESS(return (0));
116 19750
}
117
118
static int
119 9036
vslq_test_rec(const struct vex *vex, const struct VSLC_ptr *rec)
120
{
121
        const struct vex_rhs *rhs;
122 9036
        long long lhs_int = 0;
123 9036
        double lhs_float = 0.;
124
        const char *b, *e, *q;
125
        int i, dq;
126
127 9036
        AN(vex);
128 9036
        AN(rec);
129
130 9036
        b = VSL_CDATA(rec->ptr);
131 9036
        e = b + VSL_LEN(rec->ptr) - 1;
132
133
        /* Prefix */
134 9036
        if (vex->lhs->prefix != NULL) {
135 2700
                if (strncasecmp(b, vex->lhs->prefix, vex->lhs->prefixlen))
136 2075
                        return (0);
137 625
                if (b[vex->lhs->prefixlen] != ':')
138 0
                        return (0);
139 625
                b += vex->lhs->prefixlen + 1;
140
                /* Skip ws */
141 875
                while (*b && isspace(*b))
142 250
                        b++;
143 625
        }
144
145
        /* Field */
146 6961
        if (vex->lhs->field > 0) {
147 3400
                for (e = b, i = 0, dq = 0; *e && i < vex->lhs->field; i++) {
148
                        /* Skip end of previous field */
149 2725
                        if (dq) {
150 75
                                assert(e > b);
151 75
                                assert(*e == '"');
152 75
                                dq = 0;
153 75
                                e++;
154 75
                                if (*e == '\0')
155 0
                                        break;
156 75
                                if (!isspace(*e))
157 25
                                        return (0);
158 50
                        }
159
160 2700
                        b = e;
161
                        /* Skip ws */
162 5075
                        while (*b && isspace(*b))
163 2375
                                b++;
164
165 2700
                        dq = (*b == '"');
166 2700
                        if (dq)
167 275
                                b++;
168 2700
                        e = b;
169
170 2700
                        if (dq) {
171
                                /* Find end of string */
172 1600
                                while (*e && *e != '"')
173 1325
                                        e++;
174 275
                                if (*e != '"')
175 25
                                        return (0);
176 250
                        } else {
177
                                /* Skip non-ws */
178 15100
                                while (*e && !isspace(*e))
179 12675
                                        e++;
180
                        }
181 2675
                }
182 675
                assert(b <= e);
183 675
                if (*b == '\0' || i < vex->lhs->field)
184
                        /* Missing field - no match */
185 0
                        return (0);
186 675
        }
187
188 6911
        if (vex->tok == T_TRUE)
189
                /* Always true */
190 2025
                return (1);
191
192 4886
        rhs = vex->rhs;
193 4886
        CHECK_OBJ_NOTNULL(rhs, VEX_RHS_MAGIC);
194
195
        /* Prepare */
196 4886
        switch (vex->tok) {
197
        case T_EQ:              /* == */
198
        case T_NEQ:             /* != */
199
        case '<':
200
        case '>':
201
        case T_LEQ:             /* <= */
202
        case T_GEQ:             /* >= */
203
                /* Numerical comparison */
204 1850
                if (*b == '\0')
205
                        /* Empty string doesn't match */
206 0
                        return (0);
207 1850
                switch (rhs->type) {
208
                case VEX_INT:
209 1425
                        lhs_int = (long long)SF_Parse_Number(&b, 0, &q);
210 1425
                        if (errno)
211 125
                                return (0);
212 1300
                        break;
213
                case VEX_FLOAT:
214 425
                        lhs_float = SF_Parse_Decimal(&b, 0, &q);
215 425
                        if (errno)
216 75
                                return (0);
217 350
                        break;
218
                default:
219 0
                        WRONG("Wrong RHS type");
220 0
                }
221 1650
                break;
222
        default:
223 3036
                break;
224
        }
225
226
        /* Compare */
227 4686
        switch (vex->tok) {
228
        case T_EQ:              /* == */
229 1275
                VSLQ_TEST_NUMOP(rhs->type, lhs, ==, rhs->val);
230
        case T_NEQ:             /* != */
231 50
                VSLQ_TEST_NUMOP(rhs->type, lhs, !=, rhs->val);
232
        case '<':               /* < */
233 125
                VSLQ_TEST_NUMOP(rhs->type, lhs, <, rhs->val);
234
        case '>':
235 50
                VSLQ_TEST_NUMOP(rhs->type, lhs, >, rhs->val);
236
        case T_LEQ:             /* <= */
237 75
                VSLQ_TEST_NUMOP(rhs->type, lhs, <=, rhs->val);
238
        case T_GEQ:             /* >= */
239 75
                VSLQ_TEST_NUMOP(rhs->type, lhs, >=, rhs->val);
240
        case T_SEQ:             /* eq */
241 650
                assert(rhs->type == VEX_STRING);
242 650
                if (e - b != rhs->val_stringlen)
243 350
                        return (0);
244 300
                if (vex->options & VEX_OPT_CASELESS) {
245 0
                        if (strncasecmp(b, rhs->val_string, e - b))
246 0
                                return (0);
247 0
                } else {
248 300
                        if (strncmp(b, rhs->val_string, e - b))
249 0
                                return (0);
250
                }
251 300
                return (1);
252
        case T_SNEQ:            /* ne */
253 25
                assert(rhs->type == VEX_STRING);
254 25
                if (e - b != rhs->val_stringlen)
255 0
                        return (1);
256 25
                if (vex->options & VEX_OPT_CASELESS) {
257 0
                        if (strncasecmp(b, rhs->val_string, e - b))
258 0
                                return (1);
259 0
                } else {
260 25
                        if (strncmp(b, rhs->val_string, e - b))
261 25
                                return (1);
262
                }
263 0
                return (0);
264
        case '~':               /* ~ */
265 2336
                assert(rhs->type == VEX_REGEX && rhs->val_regex != NULL);
266 2336
                i = VRE_match(rhs->val_regex, b, e - b, 0, NULL);
267 2336
                if (i != VRE_ERROR_NOMATCH)
268 1249
                        return (1);
269 1087
                return (0);
270
        case T_NOMATCH:         /* !~ */
271 25
                assert(rhs->type == VEX_REGEX && rhs->val_regex != NULL);
272 25
                i = VRE_match(rhs->val_regex, b, e - b, 0, NULL);
273 25
                if (i == VRE_ERROR_NOMATCH)
274 25
                        return (1);
275 0
                return (0);
276
        default:
277 0
                WRONG("Bad expression token");
278 0
        }
279 0
        NEEDLESS(return (0));
280 9036
}
281
282
static int
283 54357
vslq_test(const struct vex *vex, struct VSL_transaction * const ptrans[])
284
{
285
        struct VSL_transaction *t;
286
        int i;
287
288 54357
        CHECK_OBJ_NOTNULL(vex, VEX_MAGIC);
289 54357
        CHECK_OBJ_NOTNULL(vex->lhs, VEX_LHS_MAGIC);
290 54357
        AN(vex->lhs->tags);
291 54357
        assert(vex->lhs->vxid <= 1);
292
293 54357
        if (vex->lhs->vxid) {
294 19750
                AZ(vex->lhs->taglist);
295 37175
                for (t = ptrans[0]; t != NULL; t = *++ptrans)
296 19750
                        if (vslq_test_vxid(vex, t))
297 2325
                                return (1);
298 17425
                return (0);
299
        }
300
301 34607
        AN(vex->lhs->taglist);
302
303 65099
        for (t = ptrans[0]; t != NULL; t = *++ptrans) {
304 35241
                if (vex->lhs->level >= 0) {
305 75
                        if (vex->lhs->level_pm < 0) {
306
                                /* OK if less than or equal */
307 25
                                if (t->level > vex->lhs->level)
308 0
                                        continue;
309 75
                        } else if (vex->lhs->level_pm > 0) {
310
                                /* OK if greater than or equal */
311 25
                                if (t->level < vex->lhs->level)
312 0
                                        continue;
313 25
                        } else {
314
                                /* OK if equal */
315 25
                                if (t->level != vex->lhs->level)
316 0
                                        continue;
317
                        }
318 75
                }
319
320 35241
                AZ(VSL_ResetCursor(t->c));
321 39528
                while (1) {
322 430214
                        i = VSL_Next(t->c);
323 430214
                        if (i < 0)
324 0
                                return (i);
325 430214
                        if (i == 0)
326 30492
                                break;
327 399722
                        assert(i == 1);
328 399722
                        AN(t->c->rec.ptr);
329
330 399722
                        if (!vbit_test(vex->lhs->tags, VSL_TAG(t->c->rec.ptr)))
331 390686
                                continue;
332
333 9036
                        i = vslq_test_rec(vex, &t->c->rec);
334 9036
                        if (i)
335 4749
                                return (i);
336
                }
337 30492
        }
338
339 29858
        return (0);
340 54357
}
341
342
static int
343 55505
vslq_exec(const struct vex *vex, struct VSL_transaction * const ptrans[])
344
{
345
        int r;
346
347 55505
        CHECK_OBJ_NOTNULL(vex, VEX_MAGIC);
348
349 55505
        switch (vex->tok) {
350
        case T_OR:
351 750
                AN(vex->a);
352 750
                AN(vex->b);
353 750
                r = vslq_exec(vex->a, ptrans);
354 750
                if (r != 0)
355 225
                        return (r);
356 525
                return (vslq_exec(vex->b, ptrans));
357
        case T_AND:
358 374
                AN(vex->a);
359 374
                AN(vex->b);
360 374
                r = vslq_exec(vex->a, ptrans);
361 374
                if (r <= 0)
362 175
                        return (r);
363 199
                return (vslq_exec(vex->b, ptrans));
364
        case T_NOT:
365 25
                AN(vex->a);
366 25
                AZ(vex->b);
367 25
                r = vslq_exec(vex->a, ptrans);
368 25
                if (r < 0)
369 0
                        return (r);
370 25
                return (!r);
371
        default:
372 54356
                return (vslq_test(vex, ptrans));
373
        }
374
        NEEDLESS(return (0));
375 55505
}
376
377
struct vslq_query *
378 4250
vslq_newquery(struct VSL_data *vsl, enum VSL_grouping_e grouping,
379
    const char *querystring)
380
{
381
        struct vsb *vsb;
382
        struct vex *vex;
383 4250
        struct vslq_query *query = NULL;
384
385 4250
        (void)grouping;
386 4250
        AN(querystring);
387
388 4250
        vsb = VSB_new_auto();
389 4250
        AN(vsb);
390 4250
        vex = vex_New(querystring, vsb, vsl->C_opt ? VEX_OPT_CASELESS : 0);
391 4250
        AZ(VSB_finish(vsb));
392 4250
        if (vex == NULL)
393 800
                vsl_diag(vsl, "%s", VSB_data(vsb));
394
        else {
395 3450
                ALLOC_OBJ(query, VSLQ_QUERY_MAGIC);
396 3450
                XXXAN(query);
397 3450
                query->vex = vex;
398
        }
399 4250
        VSB_destroy(&vsb);
400 4250
        return (query);
401
}
402
403
void
404 3450
vslq_deletequery(struct vslq_query **pquery)
405
{
406
        struct vslq_query *query;
407
408 3450
        TAKE_OBJ_NOTNULL(query, pquery, VSLQ_QUERY_MAGIC);
409
410 3450
        AN(query->vex);
411 3450
        vex_Free(&query->vex);
412 3450
        AZ(query->vex);
413
414 3450
        FREE_OBJ(query);
415 3450
}
416
417
int
418 53632
vslq_runquery(const struct vslq_query *query,
419
    struct VSL_transaction * const ptrans[])
420
{
421
        struct VSL_transaction *t;
422
        int r;
423
424 53632
        CHECK_OBJ_NOTNULL(query, VSLQ_QUERY_MAGIC);
425
426 53632
        r = vslq_exec(query->vex, ptrans);
427 108228
        for (t = ptrans[0]; t != NULL; t = *++ptrans)
428 54596
                AZ(VSL_ResetCursor(t->c));
429 53632
        return (r);
430
}