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 31828
vslq_test_vxid(const struct vex *vex, const struct VSL_transaction *trans)
78
{
79
        const struct vex_rhs *rhs;
80
81 31828
        AN(vex);
82 31828
        AN(trans);
83
84 31828
        rhs = vex->rhs;
85 31828
        CHECK_OBJ_NOTNULL(rhs, VEX_RHS_MAGIC);
86
87
        /* Prepare */
88 31828
        switch (vex->tok) {
89
        case T_EQ:              /* == */
90
        case T_NEQ:             /* != */
91
        case '<':
92
        case '>':
93
        case T_LEQ:             /* <= */
94
        case T_GEQ:             /* >= */
95 31828
                if (rhs->type != VEX_INT)
96 0
                        WRONG("Wrong RHS type for vxid");
97
                /* FALLTHROUGH */
98
        default:
99 31828
                break;
100
        }
101
102
        /* Compare */
103 31828
        switch (vex->tok) {
104
#define VXID_TEST_NUMOP(OP) return (trans->vxid OP rhs->val_int)
105 31828
        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 31828
}
117
118
static int
119 14258
vslq_test_rec(const struct vex *vex, const struct VSLC_ptr *rec)
120
{
121
        const struct vex_rhs *rhs;
122 14258
        long long lhs_int = 0;
123 14258
        double lhs_float = 0.;
124
        const char *b, *e, *q;
125
        int i, dq;
126
127 14258
        AN(vex);
128 14258
        AN(rec);
129
130 14258
        b = VSL_CDATA(rec->ptr);
131 14258
        e = b + VSL_LEN(rec->ptr) - 1;
132
133
        /* Prefix */
134 14258
        if (vex->lhs->prefix != NULL) {
135 4320
                if (strncasecmp(b, vex->lhs->prefix, vex->lhs->prefixlen))
136 3320
                        return (0);
137 1000
                if (b[vex->lhs->prefixlen] != ':')
138 0
                        return (0);
139 1000
                b += vex->lhs->prefixlen + 1;
140
                /* Skip ws */
141 1400
                while (*b && isspace(*b))
142 400
                        b++;
143 1000
        }
144
145
        /* Field */
146 10938
        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 10858
        if (vex->tok == T_TRUE)
189
                /* Always true */
190 3040
                return (1);
191
192 7818
        rhs = vex->rhs;
193 7818
        CHECK_OBJ_NOTNULL(rhs, VEX_RHS_MAGIC);
194
195
        /* Prepare */
196 7818
        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 2960
                if (*b == '\0')
205
                        /* Empty string doesn't match */
206 0
                        return (0);
207 2960
                switch (rhs->type) {
208
                case VEX_INT:
209 2280
                        lhs_int = (long long)SF_Parse_Number(&b, 0, &q);
210 2280
                        if (errno)
211 200
                                return (0);
212 2080
                        break;
213
                case VEX_FLOAT:
214 680
                        lhs_float = SF_Parse_Decimal(&b, 0, &q);
215 680
                        if (errno)
216 120
                                return (0);
217 560
                        break;
218
                default:
219 0
                        WRONG("Wrong RHS type");
220 0
                }
221 2640
                break;
222
        default:
223 4858
                break;
224
        }
225
226
        /* Compare */
227 7498
        switch (vex->tok) {
228
        case T_EQ:              /* == */
229 2040
                VSLQ_TEST_NUMOP(rhs->type, lhs, ==, rhs->val);
230
        case T_NEQ:             /* != */
231 80
                VSLQ_TEST_NUMOP(rhs->type, lhs, !=, rhs->val);
232
        case '<':               /* < */
233 200
                VSLQ_TEST_NUMOP(rhs->type, lhs, <, rhs->val);
234
        case '>':
235 80
                VSLQ_TEST_NUMOP(rhs->type, lhs, >, rhs->val);
236
        case T_LEQ:             /* <= */
237 120
                VSLQ_TEST_NUMOP(rhs->type, lhs, <=, rhs->val);
238
        case T_GEQ:             /* >= */
239 120
                VSLQ_TEST_NUMOP(rhs->type, lhs, >=, rhs->val);
240
        case T_SEQ:             /* eq */
241 1040
                assert(rhs->type == VEX_STRING);
242 1040
                if (e - b != rhs->val_stringlen)
243 560
                        return (0);
244 480
                if (vex->options & VEX_OPT_CASELESS) {
245 0
                        if (strncasecmp(b, rhs->val_string, e - b))
246 0
                                return (0);
247 0
                } else {
248 480
                        if (strncmp(b, rhs->val_string, e - b))
249 0
                                return (0);
250
                }
251 480
                return (1);
252
        case T_SNEQ:            /* ne */
253 40
                assert(rhs->type == VEX_STRING);
254 40
                if (e - b != rhs->val_stringlen)
255 0
                        return (1);
256 40
                if (vex->options & VEX_OPT_CASELESS) {
257 0
                        if (strncasecmp(b, rhs->val_string, e - b))
258 0
                                return (1);
259 0
                } else {
260 40
                        if (strncmp(b, rhs->val_string, e - b))
261 40
                                return (1);
262
                }
263 0
                return (0);
264
        case '~':               /* ~ */
265 3738
                assert(rhs->type == VEX_REGEX && rhs->val_regex != NULL);
266 3738
                i = VRE_match(rhs->val_regex, b, e - b, 0, NULL);
267 3738
                if (i != VRE_ERROR_NOMATCH)
268 2000
                        return (1);
269 1738
                return (0);
270
        case T_NOMATCH:         /* !~ */
271 40
                assert(rhs->type == VEX_REGEX && rhs->val_regex != NULL);
272 40
                i = VRE_match(rhs->val_regex, b, e - b, 0, NULL);
273 40
                if (i == VRE_ERROR_NOMATCH)
274 40
                        return (1);
275 0
                return (0);
276
        default:
277 0
                WRONG("Bad expression token");
278 0
        }
279 0
        NEEDLESS(return (0));
280 14258
}
281
282
static int
283 76120
vslq_test(const struct vex *vex, struct VSL_transaction * const ptrans[])
284
{
285
        struct VSL_transaction *t;
286
        int i;
287
288 76120
        CHECK_OBJ_NOTNULL(vex, VEX_MAGIC);
289 76120
        CHECK_OBJ_NOTNULL(vex->lhs, VEX_LHS_MAGIC);
290 76120
        AN(vex->lhs->tags);
291 76120
        assert(vex->lhs->vxid <= 1);
292
293 76120
        if (vex->lhs->vxid) {
294 31827
                AZ(vex->lhs->taglist);
295 59814
                for (t = ptrans[0]; t != NULL; t = *++ptrans)
296 31827
                        if (vslq_test_vxid(vex, t))
297 3840
                                return (1);
298 27987
                return (0);
299
        }
300
301 44293
        AN(vex->lhs->taglist);
302
303 82226
        for (t = ptrans[0]; t != NULL; t = *++ptrans) {
304 45332
                if (vex->lhs->level >= 0) {
305 120
                        if (vex->lhs->level_pm < 0) {
306
                                /* OK if less than or equal */
307 40
                                if (t->level > vex->lhs->level)
308 0
                                        continue;
309 120
                        } else if (vex->lhs->level_pm > 0) {
310
                                /* OK if greater than or equal */
311 40
                                if (t->level < vex->lhs->level)
312 0
                                        continue;
313 40
                        } else {
314
                                /* OK if equal */
315 40
                                if (t->level != vex->lhs->level)
316 0
                                        continue;
317
                        }
318 120
                }
319
320 45332
                AZ(VSL_ResetCursor(t->c));
321 52190
                while (1) {
322 671059
                        i = VSL_Next(t->c);
323 671059
                        if (i < 0)
324 0
                                return (i);
325 671059
                        if (i == 0)
326 37933
                                break;
327 633126
                        assert(i == 1);
328 633126
                        AN(t->c->rec.ptr);
329
330 633126
                        if (!vbit_test(vex->lhs->tags, VSL_TAG(t->c->rec.ptr)))
331 618869
                                continue;
332
333 14257
                        i = vslq_test_rec(vex, &t->c->rec);
334 14257
                        if (i)
335 7399
                                return (i);
336
                }
337 37933
        }
338
339 36894
        return (0);
340 76120
}
341
342
static int
343 77959
vslq_exec(const struct vex *vex, struct VSL_transaction * const ptrans[])
344
{
345
        int r;
346
347 77959
        CHECK_OBJ_NOTNULL(vex, VEX_MAGIC);
348
349 77959
        switch (vex->tok) {
350
        case T_OR:
351 1200
                AN(vex->a);
352 1200
                AN(vex->b);
353 1200
                r = vslq_exec(vex->a, ptrans);
354 1200
                if (r != 0)
355 360
                        return (r);
356 840
                return (vslq_exec(vex->b, ptrans));
357
        case T_AND:
358 599
                AN(vex->a);
359 599
                AN(vex->b);
360 599
                r = vslq_exec(vex->a, ptrans);
361 599
                if (r <= 0)
362 280
                        return (r);
363 319
                return (vslq_exec(vex->b, ptrans));
364
        case T_NOT:
365 40
                AN(vex->a);
366 40
                AZ(vex->b);
367 40
                r = vslq_exec(vex->a, ptrans);
368 40
                if (r < 0)
369 0
                        return (r);
370 40
                return (!r);
371
        default:
372 76120
                return (vslq_test(vex, ptrans));
373
        }
374
        NEEDLESS(return (0));
375 77959
}
376
377
struct vslq_query *
378 6760
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 6760
        struct vslq_query *query = NULL;
384
385 6760
        (void)grouping;
386 6760
        AN(querystring);
387
388 6760
        vsb = VSB_new_auto();
389 6760
        AN(vsb);
390 6760
        vex = vex_New(querystring, vsb, vsl->C_opt ? VEX_OPT_CASELESS : 0);
391 6760
        AZ(VSB_finish(vsb));
392 6760
        if (vex == NULL)
393 1280
                vsl_diag(vsl, "%s", VSB_data(vsb));
394
        else {
395 5480
                ALLOC_OBJ(query, VSLQ_QUERY_MAGIC);
396 5480
                XXXAN(query);
397 5480
                query->vex = vex;
398
        }
399 6760
        VSB_destroy(&vsb);
400 6760
        return (query);
401
}
402
403
void
404 5480
vslq_deletequery(struct vslq_query **pquery)
405
{
406
        struct vslq_query *query;
407
408 5480
        TAKE_OBJ_NOTNULL(query, pquery, VSLQ_QUERY_MAGIC);
409
410 5480
        AN(query->vex);
411 5480
        vex_Free(&query->vex);
412 5480
        AZ(query->vex);
413
414 5480
        FREE_OBJ(query);
415 5480
}
416
417
int
418 74959
vslq_runquery(const struct vslq_query *query,
419
    struct VSL_transaction * const ptrans[])
420
{
421
        struct VSL_transaction *t;
422
        int r;
423
424 74959
        CHECK_OBJ_NOTNULL(query, VSLQ_QUERY_MAGIC);
425
426 74959
        r = vslq_exec(query->vex, ptrans);
427 151485
        for (t = ptrans[0]; t != NULL; t = *++ptrans)
428 76526
                AZ(VSL_ResetCursor(t->c));
429 74959
        return (r);
430
}