Skip to content

Commit 47d6962

Browse files
Iselgreyrexim
authored andcommitted
Constrain 'replace' command string length to 4096
To avoid nested replace calls to consume memory exponentially
1 parent 8c36acb commit 47d6962

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

cmd/gatekeeper/command.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ func EvalContextFromCommandEnvironment(env CommandEnvironment, command Command,
221221
},
222222
"replace": func(context *EvalContext, args[]Expr) (Expr, error) {
223223
arity := 3;
224+
strlimit := 4096; // one replacement could potentially create a strlimit*strlimit string inside this block
224225
if len(args) != arity {
225226
return Expr{}, fmt.Errorf("replace: Expected %d arguments but got %d", arity, len(args))
226227
}
@@ -232,6 +233,9 @@ func EvalContextFromCommandEnvironment(env CommandEnvironment, command Command,
232233
if regExpr.Type != ExprStr {
233234
return Expr{}, fmt.Errorf("replace: Argument 1 is expected to be %s, but got %s", ExprTypeName(ExprStr), ExprTypeName(regExpr.Type))
234235
}
236+
if len(regExpr.AsStr) > strlimit {
237+
return Expr{}, fmt.Errorf("replace: regexp exceeded string size limit of %d bytes",strlimit)
238+
}
235239

236240
srcExpr, err := context.EvalExpr(args[1])
237241
if err != nil {
@@ -240,6 +244,9 @@ func EvalContextFromCommandEnvironment(env CommandEnvironment, command Command,
240244
if srcExpr.Type != ExprStr {
241245
return Expr{}, fmt.Errorf("replace: Argument 2 is expected to be %s, but got %s", ExprTypeName(ExprStr), ExprTypeName(srcExpr.Type))
242246
}
247+
if len(srcExpr.AsStr) > strlimit {
248+
return Expr{}, fmt.Errorf("replace: source exceeded string size limit of %d bytes",strlimit)
249+
}
243250

244251
replExpr, err := context.EvalExpr(args[2])
245252
if err != nil {
@@ -248,13 +255,21 @@ func EvalContextFromCommandEnvironment(env CommandEnvironment, command Command,
248255
if replExpr.Type != ExprStr {
249256
return Expr{}, fmt.Errorf("replace: Argument 3 is expected to be %s, but got %s", ExprTypeName(ExprStr), ExprTypeName(replExpr.Type))
250257
}
258+
if len(replExpr.AsStr) > strlimit {
259+
return Expr{}, fmt.Errorf("replace: replacement exceeded string size limit of %d bytes",strlimit)
260+
}
251261

252262
reg, err := regexp.Compile(regExpr.AsStr);
253263
if err != nil {
254264
return Expr{}, fmt.Errorf("replace: Could not compile regexp `%s`: %w", regExpr.AsStr, err)
255265
}
256266

257-
return NewExprStr(string(reg.ReplaceAll([]byte(srcExpr.AsStr), []byte(replExpr.AsStr)))), nil
267+
out := string(reg.ReplaceAll([]byte(srcExpr.AsStr), []byte(replExpr.AsStr)))
268+
if len(out) > strlimit {
269+
out = out[:strlimit]
270+
}
271+
272+
return NewExprStr(out), nil
258273
},
259274
"year": func(context *EvalContext, args []Expr) (Expr, error) {
260275
if len(args) > 0 {

0 commit comments

Comments
 (0)