Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .release-notes/protect-pony-lint-against-oversize-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## Protect pony-lint against oversize configuration files

pony-lint now rejects `.pony-lint.json` files larger than 64 KB. With hierarchical configuration, each directory in a project can have its own config file — an unexpectedly large file could cause excessive memory consumption. Config files that exceed the limit produce a `lint/config-error` diagnostic with the file size and path.
15 changes: 14 additions & 1 deletion tools/pony-lint/config.pony
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,23 @@ primitive ConfigLoader
=>
"""
Parse a `.pony-lint.json` file into rule status overrides.

Rejects files larger than 64 KB to prevent unexpected memory consumption,
especially with hierarchical configs where each directory can have its own
config file.
"""
let file = File.open(fp)
if not file.valid() then
return ConfigError("could not open config file: " + fp.path)
end
let content: String val = file.read_string(file.size())
let size = file.size()
if size > _max_config_size() then
file.dispose()
return ConfigError(
"config file too large (" + size.string() + " bytes, max "
+ _max_config_size().string() + "): " + fp.path)
end
let content: String val = file.read_string(size)
file.dispose()
parse(content)

Expand Down Expand Up @@ -287,6 +298,8 @@ primitive ConfigLoader
ConfigError("malformed JSON in config file: " + err.string())
end

fun _max_config_size(): USize => 65_536

fun _parse_rules(rules: json.JsonObject)
: (Map[String, RuleStatus] val | ConfigError)
=>
Expand Down
30 changes: 30 additions & 0 deletions tools/pony-lint/test/_test_config.pony
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,36 @@ class \nodoc\ _TestConfigValidateMultipleUnknown is UnitTest
h.assert_true(err.message.contains("bogus/two"))
end

class \nodoc\ _TestConfigParseFileTooLarge is UnitTest
"""Oversized config file produces ConfigError."""
fun name(): String => "Config: oversized file -> error"

fun apply(h: TestHelper) =>
let auth = h.env.root
try
let tmp = FilePath.mkdtemp(FileAuth(auth), "pony-lint-test")?
let config_fp =
FilePath(
FileAuth(auth), Path.join(tmp.path, ".pony-lint.json"))
let f = File(config_fp)
// Write 65537 bytes — one byte over the 64 KB limit
let content = recover val String(65_537) .> append("x" * 65_537) end
f.print(content)
f.dispose()

match \exhaustive\ lint.ConfigLoader.parse_file(config_fp)
| let _: Map[String, lint.RuleStatus] val =>
h.fail("expected ConfigError for oversized file")
| let err: lint.ConfigError =>
h.assert_true(err.message.contains("too large"))
end

config_fp.remove()
tmp.remove()
else
h.fail("could not create temp directory")
end

class \nodoc\ _TestConfigValidateMixedKnownUnknown is UnitTest
"""Validate only reports unknown keys, not known ones."""
fun name(): String => "Config: validate reports only unknown keys"
Expand Down
1 change: 1 addition & 0 deletions tools/pony-lint/test/main.pony
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ actor \nodoc\ Main is TestList
test(_TestConfigValidateEmptyConfig)
test(_TestConfigValidateMultipleUnknown)
test(_TestConfigValidateMixedKnownUnknown)
test(_TestConfigParseFileTooLarge)

// ConfigResolver tests
test(_TestConfigResolverNoOverrides)
Expand Down
Loading