Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
libvmod-re
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
uplex-varnish
libvmod-re
Commits
5e3a7448
Unverified
Commit
5e3a7448
authored
Jan 31, 2025
by
Nils Goroll
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Flexelinting
parent
1461d40f
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
85 additions
and
54 deletions
+85
-54
flint.lnt
src/flint.lnt
+5
-1
rvb.h
src/rvb.h
+13
-10
vmod_re.c
src/vmod_re.c
+67
-43
No files found.
src/flint.lnt
View file @
5e3a7448
...
...
@@ -2,10 +2,13 @@
-efile(766, *_if.c)
-esym(818, re) // Parameter could be const
-esym(818, task) // Parameter could be const
-esym(7
93, pcre2_*)
-esym(7
63, vmod_re_regex) // redundant
-emacro(160, container_of)
-emacro(826, container_of)
-emacro(747, WS_TASK_ALLOC_OBJ) // size is unsigned only
-emacro(747, ALLOC_OBJ) // size is unsigned only
-emacro(160, vmin) // GNU expression
// must always be included to ensure sanity
-efile(766, config.h)
-efile(537, config.h)
...
...
@@ -14,3 +17,4 @@
-e793
-e717 // do ... while()
-e663 // suspicious array to pointer
src/rvb.h
View file @
5e3a7448
...
...
@@ -88,9 +88,9 @@ rvb_vfp_status(const struct rvb *b)
AN(b); \
AN(p); \
\
AZ
(b->u.ROWR.p || b->u.ROWR.r || \
b->u.ROWR.w || b->u.ROWR.l)
;
\
AZ(b->magic || b->flags);
\
assert(!
(b->u.ROWR.p || b->u.ROWR.r || \
b->u.ROWR.w || b->u.ROWR.l)
);
\
assert(!(b->magic || b->flags));
\
\
b->magic = RVB_MAGIC; \
b->u.ROWR.p = p; \
...
...
@@ -101,14 +101,14 @@ rvb_vfp_status(const struct rvb *b)
// init for available data
static
inline
void
rvb_init_ro
(
struct
rvb
*
b
,
const
void
*
p
,
s
s
ize_t
len
)
rvb_init_ro
(
struct
rvb
*
b
,
const
void
*
p
,
size_t
len
)
{
RVB_INIT
(
ro
,
b
,
p
,
len
);
b
->
u
.
ro
.
w
=
b
->
u
.
ro
.
l
;
}
static
inline
void
rvb_init_wr
(
struct
rvb
*
b
,
void
*
p
,
s
s
ize_t
len
)
rvb_init_wr
(
struct
rvb
*
b
,
void
*
p
,
size_t
len
)
{
RVB_INIT
(
wr
,
b
,
p
,
len
);
b
->
flags
|=
RVB_F_WR
;
...
...
@@ -150,7 +150,8 @@ rvb_r(const struct rvb *b)
static
inline
size_t
rvb_rl
(
const
struct
rvb
*
b
)
{
return
(
b
->
u
.
ro
.
w
-
b
->
u
.
ro
.
r
);
assert
(
b
->
u
.
ro
.
w
>=
b
->
u
.
ro
.
r
);
return
(
size_t
)(
b
->
u
.
ro
.
w
-
b
->
u
.
ro
.
r
);
}
...
...
@@ -159,7 +160,8 @@ static inline size_t
rvb_wl
(
const
struct
rvb
*
b
)
{
assert
(
b
->
flags
&
RVB_F_WR
);
return
(
b
->
u
.
wr
.
l
-
b
->
u
.
wr
.
w
);
assert
(
b
->
u
.
wr
.
l
>=
b
->
u
.
wr
.
w
);
return
(
size_t
)(
b
->
u
.
wr
.
l
-
b
->
u
.
wr
.
w
);
}
static
inline
char
*
...
...
@@ -173,7 +175,8 @@ rvb_w(const struct rvb *b)
static
inline
size_t
rvb_size
(
const
struct
rvb
*
b
)
{
return
(
b
->
u
.
ro
.
l
-
b
->
u
.
ro
.
p
);
assert
(
b
->
u
.
ro
.
l
>=
b
->
u
.
ro
.
p
);
return
(
size_t
)(
b
->
u
.
ro
.
l
-
b
->
u
.
ro
.
p
);
}
static
void
...
...
@@ -318,7 +321,7 @@ rvb_suck(struct rvb *b, struct vfp_ctx *vc)
ssize_t
l
;
rvb_assert
(
b
);
l
=
rvb_wl
(
b
);
l
=
(
ssize_t
)
rvb_wl
(
b
);
AN
(
l
);
r
=
VFP_Suck
(
vc
,
rvb_w
(
b
),
&
l
);
...
...
@@ -453,7 +456,7 @@ rvb_vdp_bytes(struct rvb *b, struct vdp_ctx *vdx)
else
act
=
VDP_FLUSH
;
r
=
VDP_bytes
(
vdx
,
act
,
rvb_r
(
b
),
rvb_rl
(
b
));
r
=
VDP_bytes
(
vdx
,
act
,
rvb_r
(
b
),
(
ssize_t
)
rvb_rl
(
b
));
rvb_fini
(
b
);
return
(
r
);
}
src/vmod_re.c
View file @
5e3a7448
...
...
@@ -47,8 +47,6 @@
#define MAX_MATCHES 11
#define MAX_OV ((MAX_MATCHES) * 2)
struct
vmod_re_regex
;
// lack of priv pointer
// https://github.com/varnishcache/varnish-cache/pull/3912
struct
vdp_container
{
...
...
@@ -100,7 +98,7 @@ errmsg(VRT_CTX, const char *fmt, ...)
static
vre_t
*
re_compile
(
const
char
*
pattern
,
unsigned
options
,
char
*
errbuf
,
size_t
errbufsz
,
int
*
erroffset
)
s
s
ize_t
errbufsz
,
int
*
erroffset
)
{
static
vre_t
*
vre
;
struct
vsb
vsb
[
1
];
...
...
@@ -146,6 +144,11 @@ vmod_regex__init(VRT_CTX, struct vmod_re_regex **rep, const char *vcl_name,
return
;
}
if
(
limit
>
UINT_MAX
)
limit
=
UINT_MAX
;
if
(
limit_recursion
>
UINT_MAX
)
limit_recursion
=
UINT_MAX
;
forbody
|=
asfilter
;
if
(
forbody
)
...
...
@@ -166,8 +169,8 @@ vmod_regex__init(VRT_CTX, struct vmod_re_regex **rep, const char *vcl_name,
ALLOC_OBJ
(
re
,
VMOD_RE_REGEX_MAGIC
);
AN
(
re
);
re
->
vre
=
vre
;
re
->
vre_limits
.
match
=
limit
;
re
->
vre_limits
.
depth
=
limit_recursion
;
re
->
vre_limits
.
match
=
(
unsigned
)
limit
;
re
->
vre_limits
.
depth
=
(
unsigned
)
limit_recursion
;
*
rep
=
re
;
if
(
asfilter
==
0
)
...
...
@@ -241,7 +244,7 @@ init_task(VRT_CTX, struct vmod_priv *task)
AN
(
task
);
if
(
task
->
priv
==
NULL
)
task
->
priv
=
WS_Alloc
(
ctx
->
ws
,
sizeof
(
*
ov
));
task
->
priv
=
WS_Alloc
(
ctx
->
ws
,
(
unsigned
)
sizeof
(
*
ov
));
if
(
task
->
priv
==
NULL
)
{
VSLb
(
ctx
->
vsl
,
SLT_VCL_Error
,
"vmod re error: "
"insufficient workspace for backref data"
);
...
...
@@ -321,7 +324,7 @@ match(VRT_CTX, const vre_t *vre, VCL_STRING subject,
ov
->
subject
=
subject
;
for
(
i
=
0
;
i
<
s
*
2
;
i
++
)
ov
->
ovector
[
i
]
=
ovector
[
i
];
ov
->
ovector
[
i
]
=
(
int
)
ovector
[
i
];
for
(
;
i
<
MAX_OV
;
i
++
)
ov
->
ovector
[
i
]
=
-
1
;
...
...
@@ -389,13 +392,18 @@ get_limits(const struct vmod_re_regex *re, struct vre_limits *limits,
if
(
limit
<=
0
&&
limit_recursion
<=
0
)
return
(
&
re
->
vre_limits
);
if
(
limit
>
UINT_MAX
)
limit
=
UINT_MAX
;
if
(
limit_recursion
>
UINT_MAX
)
limit_recursion
=
UINT_MAX
;
if
(
limit
>
0
)
limits
->
match
=
limit
;
limits
->
match
=
(
unsigned
)
limit
;
else
limits
->
match
=
re
->
vre_limits
.
match
;
if
(
limit_recursion
>
0
)
limits
->
depth
=
limit_recursion
;
limits
->
depth
=
(
unsigned
)
limit_recursion
;
else
limits
->
depth
=
re
->
vre_limits
.
depth
;
...
...
@@ -423,7 +431,7 @@ vmod_regex_match(VRT_CTX, struct vmod_re_regex *re, VCL_STRING subject,
AN
(
task
);
task
->
len
=
0
;
return
(
match
(
ctx
,
re
->
vre
,
subject
,
PCRE2_ZERO_TERMINATED
,
0
,
0
,
return
(
match
(
ctx
,
re
->
vre
,
subject
,
PCRE2_ZERO_TERMINATED
,
0
UL
,
0
,
task
,
get_limits
(
re
,
&
buf
,
limit
,
limit_recursion
))
>
PCRE2_ERROR_NOMATCH
);
}
...
...
@@ -455,9 +463,10 @@ vmod_regex_foreach(VRT_CTX, struct vmod_re_regex *re, VCL_STRING subject,
return
(
0
);
ov
=
(
ov_t
*
)
task
->
priv
;
assert
(
ov
->
ovector
[
1
]
>=
0
);
while
(
!
VRT_handled
(
ctx
)
&&
match
(
ctx
,
re
->
vre
,
subject
,
PCRE2_ZERO_TERMINATED
,
ov
->
ovector
[
1
],
0
,
(
size_t
)(
unsigned
)
ov
->
ovector
[
1
],
0
,
task
,
get_limits
(
re
,
&
buf
,
limit
,
limit_recursion
))
>
PCRE2_ERROR_NOMATCH
)
VRT_call
(
ctx
,
sub
);
...
...
@@ -494,16 +503,20 @@ reip_free(struct re_iter_priv *reip, int ret)
static
int
reip_iter
(
struct
re_iter_priv
*
reip
,
unsigned
flush
,
const
void
*
ptr
,
ssize_t
len
)
const
void
*
ptr
,
ssize_t
len
a
)
{
VCL_STRING
subject
;
// where data from ptr starts in subject
s
s
ize_t
ptrsubjoff
;
size_t
ptrsubjoff
;
ov_t
*
ov
;
int
i
;
size_t
len
;
CHECK_OBJ_NOTNULL
(
reip
,
RE_ITER_PRIV_MAGIC
);
assert
(
lena
>=
0
);
len
=
(
size_t
)
lena
;
#ifdef ITERDBG
VSLb
(
reip
->
ctx
->
vsl
,
SLT_Debug
,
"reip_iter reip { .s=%d, "
"buf/len=%p/%zu (%.*s), "
...
...
@@ -515,19 +528,17 @@ reip_iter(struct re_iter_priv *reip, unsigned flush,
flush
,
ptr
,
len
,
(
int
)
len
,
ptr
?
(
const
char
*
)
ptr
:
""
);
#endif
subject
=
ptr
;
ptrsubjoff
=
0
;
if
(
reip
->
s
>
PCRE2_ERROR_NOMATCH
)
{
AZ
(
reip
->
buf
);
AZ
(
reip
->
len
);
subject
=
ptr
;
ptrsubjoff
=
0
;
}
else
if
(
reip
->
s
==
PCRE2_ERROR_NOMATCH
)
{
AZ
(
reip
->
startoffset
);
AZ
(
reip
->
buf
);
AZ
(
reip
->
len
);
subject
=
ptr
;
ptrsubjoff
=
0
;
}
else
if
(
reip
->
s
==
PCRE2_ERROR_PARTIAL
)
{
ptrsubjoff
=
reip
->
len
;
...
...
@@ -589,11 +600,13 @@ reip_iter(struct re_iter_priv *reip, unsigned flush,
assert
(
reip
->
s
>
PCRE2_ERROR_NOMATCH
);
assert
(
ov
->
ovector
[
1
]
>=
0
);
// save start offset for next call, relative to ptr
if
(
reip
->
buf
==
NULL
)
reip
->
startoffset
=
ov
->
ovector
[
1
];
else
if
(
ov
->
ovector
[
1
]
>=
ptrsubjoff
)
reip
->
startoffset
=
ov
->
ovector
[
1
]
-
ptrsubjoff
;
reip
->
startoffset
=
(
unsigned
)
ov
->
ovector
[
1
];
else
if
(
(
unsigned
)
ov
->
ovector
[
1
]
>=
ptrsubjoff
)
reip
->
startoffset
=
(
unsigned
)
ov
->
ovector
[
1
]
-
ptrsubjoff
;
else
WRONG
(
"impossible ovector[1]"
);
...
...
@@ -608,11 +621,13 @@ reip_iter(struct re_iter_priv *reip, unsigned flush,
*/
assert
(
ov
->
ovector
[
0
]
>=
0
);
assert
(
ov
->
ovector
[
1
]
>=
ov
->
ovector
[
0
]);
len
=
(
typeof
(
len
))
ov
->
ovector
[
1
]
-
(
typeof
(
len
))
ov
->
ovector
[
0
];
assert
(
len
>=
0
);
lena
=
(
typeof
(
lena
))
ov
->
ovector
[
1
]
-
(
typeof
(
lena
))
ov
->
ovector
[
0
];
assert
(
lena
>=
0
);
assert
(
lena
<=
INT_MAX
);
int
l
=
(
int
)
lena
;
ov
->
subject
=
(
l
en
==
0
)
?
""
:
WS_Copy
(
reip
->
ctx
->
ws
,
subject
+
ov
->
ovector
[
0
],
l
en
);
ov
->
subject
=
(
l
==
0
)
?
""
:
WS_Copy
(
reip
->
ctx
->
ws
,
subject
+
ov
->
ovector
[
0
],
l
);
if
(
ov
->
subject
==
NULL
)
{
errmsg
(
reip
->
ctx
,
"vmod re: insufficient workspace "
...
...
@@ -621,10 +636,10 @@ reip_iter(struct re_iter_priv *reip, unsigned flush,
}
/* we have copied subject from start of match, fix all offsets */
l
en
=
ov
->
ovector
[
0
];
l
=
ov
->
ovector
[
0
];
for
(
i
=
0
;
i
<
reip
->
s
*
2
;
i
++
)
{
assert
(
ov
->
ovector
[
i
]
>=
l
en
);
ov
->
ovector
[
i
]
-=
l
en
;
assert
(
ov
->
ovector
[
i
]
>=
l
);
ov
->
ovector
[
i
]
-=
l
;
}
return
(
reip_free
(
reip
,
0
));
...
...
@@ -725,7 +740,7 @@ reip_match_body(struct re_iter_priv *reip, struct vmod_re_regex *re,
// XXX core code does not send OBJ_ITER_END reliably
if
(
reip
->
s
==
PCRE2_ERROR_PARTIAL
)
(
void
)
iter
(
reip
,
OBJ_ITER_END
,
""
,
0
);
(
void
)
iter
(
reip
,
OBJ_ITER_END
,
""
,
0
L
);
AZ
(
reip
->
buf
);
...
...
@@ -835,8 +850,13 @@ vmod_match_dyn(VRT_CTX, struct vmod_priv *task, VCL_STRING pattern,
return
0
;
}
limits
.
match
=
limit
;
limits
.
depth
=
limit_recursion
;
if
(
limit
>
UINT_MAX
)
limit
=
UINT_MAX
;
if
(
limit_recursion
>
UINT_MAX
)
limit_recursion
=
UINT_MAX
;
limits
.
match
=
(
unsigned
)
limit
;
limits
.
depth
=
(
unsigned
)
limit_recursion
;
task
->
len
=
0
;
vre
=
re_compile
(
pattern
,
0
,
errbuf
,
sizeof
errbuf
,
&
erroffset
);
...
...
@@ -847,7 +867,7 @@ vmod_match_dyn(VRT_CTX, struct vmod_priv *task, VCL_STRING pattern,
return
0
;
}
dyn_return
=
(
match
(
ctx
,
vre
,
subject
,
PCRE2_ZERO_TERMINATED
,
0
,
0
,
dyn_return
=
(
match
(
ctx
,
vre
,
subject
,
PCRE2_ZERO_TERMINATED
,
0
L
,
0
,
task
,
&
limits
)
>
PCRE2_ERROR_NOMATCH
);
...
...
@@ -973,7 +993,7 @@ VCL_VOID vmod_regex_substitute_all(VRT_CTX,
struct
VPFX
(
re_regex
)
*
re
,
VCL_STRING
s
)
{
vmod_regex_clear_substitutions
(
ctx
,
re
);
vmod_regex_substitute_match
(
ctx
,
re
,
0
,
s
);
vmod_regex_substitute_match
(
ctx
,
re
,
0
L
,
s
);
}
VCL_VOID
vmod_regex_clear_substitutions
(
VRT_CTX
,
...
...
@@ -1157,6 +1177,7 @@ re_vfp_subst(struct rvb *out, struct rvb *overflow,
const
char
*
s
,
*
e
;
unsigned
x
;
//lint -e{850} loop variable e modified
for
(
s
=
e
=
replacement
;
*
e
!=
'\0'
;
e
++
)
{
if
(
*
e
!=
'\\'
||
e
[
1
]
==
'\0'
)
continue
;
...
...
@@ -1164,12 +1185,13 @@ re_vfp_subst(struct rvb *out, struct rvb *overflow,
s
=
++
e
;
if
(
xisdigit
(
*
e
))
{
s
++
;
x
=
*
e
-
'0'
;
x
=
(
unsigned
char
)
*
e
;
x
-=
'0'
;
if
(
x
>=
matches
)
continue
;
x
*=
2
;
rvb_puto
(
out
,
overflow
,
subj
+
ovector
[
x
],
ovector
[
x
+
1
]
-
ovector
[
x
]);
ovector
[
x
|
1
]
-
ovector
[
x
]);
continue
;
}
}
...
...
@@ -1239,6 +1261,7 @@ re_vfp_pull(struct vfp_ctx *vc, struct vfp_entry *vfe,
CAST_OBJ_NOTNULL
(
res
,
vfe
->
priv1
,
RE_FLT_STATE_MAGIC
);
AN
(
p
);
AN
(
lp
);
assert
(
*
lp
>=
0
);
#ifdef TEST_REDUCED_BUFFER
*
lp
=
TEST_REDUCED_BUFFER
;
...
...
@@ -1246,7 +1269,7 @@ re_vfp_pull(struct vfp_ctx *vc, struct vfp_entry *vfe,
TEST_REDUCED_BUFFER
);
#endif
rvb_init_wr
(
out
,
p
,
*
lp
);
rvb_init_wr
(
out
,
p
,
(
size_t
)
*
lp
);
*
lp
=
0
;
if
(
rvb_is
(
res
->
i
)
&&
rvb_rl
(
res
->
i
)
>
0
)
...
...
@@ -1330,7 +1353,7 @@ suck:
* make it work without first and maybe revisit later
*/
i
=
pcre2_match
(
res
->
re
,
(
PCRE2_SPTR
)
rvb_r
(
b
),
rvb_rl
(
b
),
0
,
i
=
pcre2_match
(
res
->
re
,
(
PCRE2_SPTR
)
rvb_r
(
b
),
rvb_rl
(
b
),
0
UL
,
res
->
re_options
,
res
->
re_data
,
res
->
re_ctx
);
if
(
i
<
PCRE2_ERROR_PARTIAL
)
{
...
...
@@ -1347,7 +1370,7 @@ suck:
if
(
b
==
res
->
i
)
{
rvb_compact
(
b
);
rvb_grow
(
b
,
0
);
rvb_grow
(
b
,
0
UL
);
goto
suck
;
}
...
...
@@ -1585,7 +1608,8 @@ re_vdp_bytes(struct vdp_ctx *vdx, enum vdp_action act, void **priv,
if
(
len
==
0
&&
ptr
==
NULL
)
ptr
=
""
;
rvb_init_ro
(
in
,
ptr
,
len
);
assert
(
len
>=
0
);
rvb_init_ro
(
in
,
ptr
,
(
size_t
)
len
);
if
(
act
==
VDP_END
)
in
->
flags
|=
RVB_F_END
;
else
if
(
act
==
VDP_NULL
)
...
...
@@ -1626,7 +1650,7 @@ more:
* make it work without first and maybe revisit later
*/
i
=
pcre2_match
(
res
->
re
,
(
PCRE2_SPTR
)
rvb_r
(
b
),
rvb_rl
(
b
),
0
,
i
=
pcre2_match
(
res
->
re
,
(
PCRE2_SPTR
)
rvb_r
(
b
),
rvb_rl
(
b
),
0
UL
,
res
->
re_options
,
res
->
re_data
,
res
->
re_ctx
);
if
(
i
<
PCRE2_ERROR_PARTIAL
)
{
...
...
@@ -1673,7 +1697,7 @@ more:
else
act
=
VDP_NULL
;
r
=
VDP_bytes
(
vdx
,
act
,
rvb_r
(
b
),
ovector
[
1
]);
r
=
VDP_bytes
(
vdx
,
act
,
rvb_r
(
b
),
(
ssize_t
)
ovector
[
1
]);
rvb_consume
(
b
,
ovector
[
1
]);
...
...
@@ -1709,9 +1733,9 @@ more:
act
=
VDP_NULL
;
if
(
sub
->
flags
&
REFS_F_FIXED
)
r
=
VDP_bytes
(
vdx
,
act
,
sub
->
s
,
strlen
(
sub
->
s
));
r
=
VDP_bytes
(
vdx
,
act
,
sub
->
s
,
(
ssize_t
)
strlen
(
sub
->
s
));
else
r
=
re_vdp_subst
(
vdx
,
act
,
sub
->
s
,
ovector
,
rvb_r
(
b
),
i
);
r
=
re_vdp_subst
(
vdx
,
act
,
sub
->
s
,
ovector
,
rvb_r
(
b
),
(
unsigned
)
i
);
AZ
(
ovector
[
0
]);
rvb_consume
(
b
,
ovector
[
1
]);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment