varnish-cache/bin/varnishd/cache/cache_vrt_re.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2015 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 *
29
 * Runtime support for compiled VCL programs, regexps
30
 */
31
32
#include "config.h"
33
34
#include <ctype.h>
35
36
#include "cache_varnishd.h"
37
38
static void
39 136
Tadd(char **b, char *e, const char *p, int l)
40
{
41 136
        assert((*b) <= e);
42
43
        if (l <= 0) {
44 136
        } if ((*b) + l < e) {
45 136
                memcpy((*b), p, l);
46 136
                (*b) += l;
47
        } else {
48 0
                (*b) = e;
49
        }
50 136
}
51
52
void
53 3056
VRT_re_init(void **rep, const char *re)
54
{
55
        vre_t *t;
56
        const char *error;
57
        int erroroffset;
58
59
        /* This was already check-compiled by the VCL compiler */
60 3056
        t = VRE_compile(re, 0, &error, &erroroffset);
61 3056
        AN(t);
62 3056
        *rep = t;
63 3056
}
64
65
void
66 140
VRT_re_fini(void *rep)
67
{
68
        vre_t *vv;
69
70 140
        vv = rep;
71 140
        if (rep != NULL)
72 140
                VRE_free(&vv);
73 140
}
74
75
int
76 3762
VRT_re_match(VRT_CTX, const char *s, void *re)
77
{
78
        vre_t *t;
79
        int i;
80
81 3762
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
82 3762
        if (s == NULL)
83 3594
                s = "";
84 3762
        AN(re);
85 3762
        t = re;
86 3762
        i = VRE_exec(t, s, strlen(s), 0, 0, NULL, 0, &cache_param->vre_limits);
87 3762
        if (i >= 0)
88 60
                return (1);
89 3702
        if (i < VRE_ERROR_NOMATCH )
90 0
                VSLb(ctx->vsl, SLT_VCL_Error, "Regexp matching returned %d", i);
91 3702
        return (0);
92
}
93
94
const char *
95 92
VRT_regsub(VRT_CTX, int all, const char *str, void *re,
96
    const char *sub)
97
{
98
        int ovector[30];
99
        vre_t *t;
100
        int i, l;
101
        char *res_b;
102
        char *res_e;
103
        char *b0;
104
        const char *s;
105
        unsigned u, x;
106 92
        int options = 0;
107 92
        int offset = 0;
108
        size_t len;
109
110 92
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
111 92
        AN(re);
112 92
        if (str == NULL)
113 4
                str = "";
114 92
        if (sub == NULL)
115 2
                sub = "";
116 92
        t = re;
117 92
        memset(ovector, 0, sizeof(ovector));
118 92
        len = strlen(str);
119 92
        i = VRE_exec(t, str, len, 0, options, ovector, 30,
120 92
            &cache_param->vre_limits);
121
122
        /* If it didn't match, we can return the original string */
123 92
        if (i == VRE_ERROR_NOMATCH)
124 44
                return(str);
125 48
        if (i < VRE_ERROR_NOMATCH ) {
126 0
                VSLb(ctx->vsl, SLT_VCL_Error, "Regexp matching returned %d", i);
127 0
                return(str);
128
        }
129
130 48
        u = WS_Reserve(ctx->ws, 0);
131 48
        res_e = res_b = b0 = ctx->ws->f;
132 48
        res_e += u;
133
134
        do {
135
                /* Copy prefix to match */
136 52
                Tadd(&res_b, res_e, str + offset, ovector[0] - offset);
137 322
                for (s = sub ; *s != '\0'; s++ ) {
138 270
                        if (*s != '\\' || s[1] == '\0') {
139 226
                                if (res_b < res_e)
140 226
                                        *res_b++ = *s;
141 226
                                continue;
142
                        }
143 44
                        s++;
144 44
                        if (isdigit(*s)) {
145 36
                                x = *s - '0';
146 36
                                l = ovector[2*x+1] - ovector[2*x];
147 36
                                Tadd(&res_b, res_e, str + ovector[2*x], l);
148 36
                                continue;
149
                        } else {
150 8
                                if (res_b < res_e)
151 8
                                        *res_b++ = *s;
152
                        }
153
                }
154 52
                offset = ovector[1];
155 52
                if (!all)
156 30
                        break;
157 22
                memset(ovector, 0, sizeof(ovector));
158 22
                options |= VRE_NOTEMPTY;
159 22
                i = VRE_exec(t, str, len, offset, options, ovector, 30,
160 22
                    &cache_param->vre_limits);
161 22
                if (i < VRE_ERROR_NOMATCH ) {
162 0
                        WS_Release(ctx->ws, 0);
163 0
                        VSLb(ctx->vsl, SLT_VCL_Error,
164
                            "Regexp matching returned %d", i);
165 0
                        return(str);
166
                }
167 22
        } while (i != VRE_ERROR_NOMATCH);
168
169
        /* Copy suffix to match */
170 48
        Tadd(&res_b, res_e, str + offset, 1 + len - offset);
171 48
        if (res_b >= res_e) {
172 0
                WS_MarkOverflow(ctx->ws);
173 0
                WS_Release(ctx->ws, 0);
174 0
                return (str);
175
        }
176 48
        assert(res_b <= res_e);
177 48
        WS_ReleaseP(ctx->ws, res_b);
178 48
        return (b0);
179
}