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 "vqueue.h"
44
#include "vre.h"
45
#include "vsb.h"
46
47
#include "vapi/vsl.h"
48
49
#include "vsl_api.h"
50
#include "vxp.h"
51
52
struct vslq_query {
53
        unsigned                magic;
54
#define VSLQ_QUERY_MAGIC        0x122322A5
55
56
        struct vex              *vex;
57
};
58
59
#define VSLQ_TEST_NUMOP(TYPE, PRE_LHS, OP, PRE_RHS)             \
60
        do {                                                    \
61
                switch (TYPE) {                                 \
62
                case VEX_INT:                                   \
63
                        if (PRE_LHS##_int OP PRE_RHS##_int)     \
64
                                return (1);                     \
65
                        return (0);                             \
66
                case VEX_FLOAT:                                 \
67
                        if (PRE_LHS##_float OP PRE_RHS##_float) \
68
                                return (1);                     \
69
                        return (0);                             \
70
                default:                                        \
71
                        WRONG("Wrong RHS type");                \
72
                }                                               \
73
        } while(0)                                              \
74
75
static int
76 31880
vslq_test_vxid(const struct vex *vex, const struct VSL_transaction *trans)
77
{
78
        const struct vex_rhs *rhs;
79
80 31880
        AN(vex);
81 31880
        AN(trans);
82
83 31880
        rhs = vex->rhs;
84 31880
        CHECK_OBJ_NOTNULL(rhs, VEX_RHS_MAGIC);
85
86
        /* Prepare */
87 31880
        switch (vex->tok) {
88
        case T_EQ:              /* == */
89
        case T_NEQ:             /* != */
90
        case '<':
91
        case '>':
92
        case T_LEQ:             /* <= */
93
        case T_GEQ:             /* >= */
94 31880
                if (rhs->type != VEX_INT)
95 0
                        WRONG("Wrong RHS type for vxid");
96
                /* FALLTHROUGH */
97
        default:
98 31880
                break;
99
        }
100
101
        /* Compare */
102 31880
        switch (vex->tok) {
103
#define VXID_TEST_NUMOP(OP) return (trans->vxid OP rhs->val_int)
104 31880
        case T_EQ:      VXID_TEST_NUMOP(==);
105 0
        case T_NEQ:     VXID_TEST_NUMOP(!=);
106 0
        case '<':       VXID_TEST_NUMOP(<);
107 0
        case '>':       VXID_TEST_NUMOP(>);
108 0
        case T_LEQ:     VXID_TEST_NUMOP(<=);
109 0
        case T_GEQ:     VXID_TEST_NUMOP(>=);
110
        #undef VXID_TEST_NUMOP
111 0
        default:        WRONG("Bad vxid expression token");
112 0
        }
113
114 0
        NEEDLESS(return (0));
115 31880
}
116
117
static int
118 15416
vslq_test_rec(const struct vex *vex, const struct VSLC_ptr *rec)
119
{
120
        const struct vex_rhs *rhs;
121 15416
        long long lhs_int = 0;
122 15416
        double lhs_float = 0.;
123
        const char *b, *e;
124
        int i, dq;
125 15416
        char *q = NULL;
126
127 15416
        AN(vex);
128 15416
        AN(rec);
129
130 15416
        b = VSL_CDATA(rec->ptr);
131 15416
        e = b + VSL_LEN(rec->ptr) - 1;
132
133
        /* Prefix */
134 15416
        if (vex->lhs->prefix != NULL) {
135 4360
                if (strncasecmp(b, vex->lhs->prefix, vex->lhs->prefixlen))
136 3320
                        return (0);
137 1040
                if (b[vex->lhs->prefixlen] != ':')
138 0
                        return (0);
139 1040
                b += vex->lhs->prefixlen + 1;
140
                /* Skip ws */
141 1480
                while (*b && isspace(*b))
142 440
                        b++;
143 1040
        }
144
145
        /* Field */
146 12096
        if (vex->lhs->field > 0) {
147 5440
                for (e = b, i = 0, dq = 0; *e && i < vex->lhs->field; i++) {
148
                        /* Skip end of previous field */
149 4360
                        if (dq) {
150 120
                                assert(e > b);
151 120
                                assert(*e == '"');
152 120
                                dq = 0;
153 120
                                e++;
154 120
                                if (*e == '\0')
155 0
                                        break;
156 120
                                if (!isspace(*e))
157 40
                                        return (0);
158 80
                        }
159
160 4320
                        b = e;
161
                        /* Skip ws */
162 8120
                        while (*b && isspace(*b))
163 3800
                                b++;
164
165 4320
                        dq = (*b == '"');
166 4320
                        if (dq)
167 440
                                b++;
168 4320
                        e = b;
169
170 4320
                        if (dq) {
171
                                /* Find end of string */
172 2560
                                while (*e && *e != '"')
173 2120
                                        e++;
174 440
                                if (*e != '"')
175 40
                                        return (0);
176 400
                        } else {
177
                                /* Skip non-ws */
178 24160
                                while (*e && !isspace(*e))
179 20280
                                        e++;
180
                        }
181 4280
                }
182 1080
                assert(b <= e);
183 1080
                if (*b == '\0' || i < vex->lhs->field)
184
                        /* Missing field - no match */
185 0
                        return (0);
186 1080
        }
187
188 12016
        if (vex->tok == T_TRUE)
189
                /* Always true */
190 4160
                return (1);
191
192 7856
        rhs = vex->rhs;
193 7856
        CHECK_OBJ_NOTNULL(rhs, VEX_RHS_MAGIC);
194
195
        /* Prepare */
196 7856
        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 3000
                if (*b == '\0')
205
                        /* Empty string doesn't match */
206 0
                        return (0);
207 3000
                errno = 0;
208 3000
                switch (rhs->type) {
209
                case VEX_INT:
210 2280
                        lhs_int = strtoll(b, &q, 0);
211 2280
                        AN(q);
212 2280
                        if (q != e && (*q == '.' || *q == 'e')) {
213 200
                                errno = 0;
214 200
                                lhs_float = strtod(b, &q);
215 200
                                lhs_int = (long long)lhs_float;
216 200
                                lhs_float = 0.;
217 200
                        }
218 2280
                        break;
219
                case VEX_FLOAT:
220 720
                        lhs_float = strtod(b, &q);
221 720
                        break;
222
                default:
223 0
                        WRONG("Wrong RHS type");
224 0
                }
225 3000
                if (q != e || errno != 0)
226 320
                        return (0);
227 2680
                break;
228
        default:
229 4856
                break;
230
        }
231
232
        /* Compare */
233 7536
        switch (vex->tok) {
234
        case T_EQ:              /* == */
235 2040
                VSLQ_TEST_NUMOP(rhs->type, lhs, ==, rhs->val);
236
        case T_NEQ:             /* != */
237 80
                VSLQ_TEST_NUMOP(rhs->type, lhs, !=, rhs->val);
238
        case '<':               /* < */
239 200
                VSLQ_TEST_NUMOP(rhs->type, lhs, <, rhs->val);
240
        case '>':
241 120
                VSLQ_TEST_NUMOP(rhs->type, lhs, >, rhs->val);
242
        case T_LEQ:             /* <= */
243 120
                VSLQ_TEST_NUMOP(rhs->type, lhs, <=, rhs->val);
244
        case T_GEQ:             /* >= */
245 120
                VSLQ_TEST_NUMOP(rhs->type, lhs, >=, rhs->val);
246
        case T_SEQ:             /* eq */
247 1040
                assert(rhs->type == VEX_STRING);
248 1040
                if (e - b != rhs->val_stringlen)
249 560
                        return (0);
250 480
                if (vex->options & VEX_OPT_CASELESS) {
251 0
                        if (strncasecmp(b, rhs->val_string, e - b))
252 0
                                return (0);
253 0
                } else {
254 480
                        if (strncmp(b, rhs->val_string, e - b))
255 0
                                return (0);
256
                }
257 480
                return (1);
258
        case T_SNEQ:            /* ne */
259 40
                assert(rhs->type == VEX_STRING);
260 40
                if (e - b != rhs->val_stringlen)
261 0
                        return (1);
262 40
                if (vex->options & VEX_OPT_CASELESS) {
263 0
                        if (strncasecmp(b, rhs->val_string, e - b))
264 0
                                return (1);
265 0
                } else {
266 40
                        if (strncmp(b, rhs->val_string, e - b))
267 40
                                return (1);
268
                }
269 0
                return (0);
270
        case '~':               /* ~ */
271 3736
                assert(rhs->type == VEX_REGEX && rhs->val_regex != NULL);
272 3736
                i = VRE_match(rhs->val_regex, b, e - b, 0, NULL);
273 3736
                if (i != VRE_ERROR_NOMATCH)
274 2000
                        return (1);
275 1736
                return (0);
276
        case T_NOMATCH:         /* !~ */
277 40
                assert(rhs->type == VEX_REGEX && rhs->val_regex != NULL);
278 40
                i = VRE_match(rhs->val_regex, b, e - b, 0, NULL);
279 40
                if (i == VRE_ERROR_NOMATCH)
280 40
                        return (1);
281 0
                return (0);
282
        default:
283 0
                WRONG("Bad expression token");
284 0
        }
285 0
        NEEDLESS(return (0));
286 15416
}
287
288
static int
289 103584
vslq_test(const struct vex *vex, struct VSL_transaction * const ptrans[])
290
{
291
        struct VSL_transaction *t;
292
        int i;
293
294 103584
        CHECK_OBJ_NOTNULL(vex, VEX_MAGIC);
295 103584
        CHECK_OBJ_NOTNULL(vex->lhs, VEX_LHS_MAGIC);
296 103584
        AN(vex->lhs->tags);
297 103584
        assert(vex->lhs->vxid <= 1);
298
299 103584
        if (vex->lhs->vxid) {
300 31879
                AZ(vex->lhs->taglist);
301 59918
                for (t = ptrans[0]; t != NULL; t = *++ptrans)
302 31879
                        if (vslq_test_vxid(vex, t))
303 3840
                                return (1);
304 28039
                return (0);
305
        }
306
307 71705
        AN(vex->lhs->taglist);
308
309 135890
        for (t = ptrans[0]; t != NULL; t = *++ptrans) {
310 72745
                if (vex->lhs->level >= 0) {
311 120
                        if (vex->lhs->level_pm < 0) {
312
                                /* OK if less than or equal */
313 40
                                if (t->level > vex->lhs->level)
314 0
                                        continue;
315 120
                        } else if (vex->lhs->level_pm > 0) {
316
                                /* OK if greater than or equal */
317 40
                                if (t->level < vex->lhs->level)
318 0
                                        continue;
319 40
                        } else {
320
                                /* OK if equal */
321 40
                                if (t->level != vex->lhs->level)
322 0
                                        continue;
323
                        }
324 120
                }
325
326 72745
                AZ(VSL_ResetCursor(t->c));
327 79601
                while (1) {
328 716910
                        i = VSL_Next(t->c);
329 716910
                        if (i < 0)
330 0
                                return (i);
331 716910
                        if (i == 0)
332 64185
                                break;
333 652725
                        assert(i == 1);
334 652725
                        AN(t->c->rec.ptr);
335
336 652725
                        if (!vbit_test(vex->lhs->tags, VSL_TAG(t->c->rec.ptr)))
337 637309
                                continue;
338
339 15416
                        i = vslq_test_rec(vex, &t->c->rec);
340 15416
                        if (i)
341 8560
                                return (i);
342
                }
343 64185
        }
344
345 63145
        return (0);
346 103584
}
347
348
static int
349 105429
vslq_exec(const struct vex *vex, struct VSL_transaction * const ptrans[])
350
{
351
        int r;
352
353 105429
        CHECK_OBJ_NOTNULL(vex, VEX_MAGIC);
354
355 105429
        switch (vex->tok) {
356
        case T_OR:
357 1200
                AN(vex->a);
358 1200
                AN(vex->b);
359 1200
                r = vslq_exec(vex->a, ptrans);
360 1200
                if (r != 0)
361 360
                        return (r);
362 840
                return (vslq_exec(vex->b, ptrans));
363
        case T_AND:
364 599
                AN(vex->a);
365 599
                AN(vex->b);
366 599
                r = vslq_exec(vex->a, ptrans);
367 599
                if (r <= 0)
368 279
                        return (r);
369 320
                return (vslq_exec(vex->b, ptrans));
370
        case T_NOT:
371 40
                AN(vex->a);
372 40
                AZ(vex->b);
373 40
                r = vslq_exec(vex->a, ptrans);
374 40
                if (r < 0)
375 0
                        return (r);
376 40
                return (!r);
377
        default:
378 103590
                return (vslq_test(vex, ptrans));
379
        }
380
        NEEDLESS(return (0));
381 105429
}
382
383
struct vslq_query *
384 7000
vslq_newquery(struct VSL_data *vsl, enum VSL_grouping_e grouping,
385
    const char *querystring)
386
{
387
        struct vsb *vsb;
388
        struct vex *vex;
389 7000
        struct vslq_query *query = NULL;
390
391 7000
        (void)grouping;
392 7000
        AN(querystring);
393
394 7000
        vsb = VSB_new_auto();
395 7000
        AN(vsb);
396 7000
        vex = vex_New(querystring, vsb, vsl->C_opt ? VEX_OPT_CASELESS : 0);
397 7000
        AZ(VSB_finish(vsb));
398 7000
        if (vex == NULL)
399 1280
                vsl_diag(vsl, "%s", VSB_data(vsb));
400
        else {
401 5720
                ALLOC_OBJ(query, VSLQ_QUERY_MAGIC);
402 5720
                XXXAN(query);
403 5720
                query->vex = vex;
404
        }
405 7000
        VSB_destroy(&vsb);
406 7000
        return (query);
407
}
408
409
void
410 5720
vslq_deletequery(struct vslq_query **pquery)
411
{
412
        struct vslq_query *query;
413
414 5720
        TAKE_OBJ_NOTNULL(query, pquery, VSLQ_QUERY_MAGIC);
415
416 5720
        AN(query->vex);
417 5720
        vex_Free(&query->vex);
418 5720
        AZ(query->vex);
419
420 5720
        FREE_OBJ(query);
421 5720
}
422
423
int
424 102429
vslq_runquery(const struct vslq_query *query,
425
    struct VSL_transaction * const ptrans[])
426
{
427
        struct VSL_transaction *t;
428
        int r;
429
430 102429
        CHECK_OBJ_NOTNULL(query, VSLQ_QUERY_MAGIC);
431
432 102429
        r = vslq_exec(query->vex, ptrans);
433 206423
        for (t = ptrans[0]; t != NULL; t = *++ptrans)
434 103994
                AZ(VSL_ResetCursor(t->c));
435 102429
        return (r);
436
}