Fix 6751 loglevel param type validation - #7923
Draft
SoubeDev wants to merge 3 commits into
Draft
Conversation
doLogLevel read both parameters with an unguarded asString(), which throws for arrays and objects and silently stringifies every scalar. The throw was swallowed by callMethod's catch-all, so a malformed value produced a generic internal error rather than invalidParams, and the request was recorded as a server fault in the perf log. The severity path was only half broken: a coerced scalar still failed Logs::fromString and came back as invalidParams, so just arrays and objects misbehaved. The partition path had no downstream validation at all, and Logs::get creates a sink on demand, so a coerced value permanently added a partition named "42", "true" or "" to the map that log_level itself then reported on every subsequent call. Guard both conversions with an isString() check and return invalidParams when it fails. Reject the empty partition name for the same reason the type check exists: it is not a partition anyone can have meant, and accepting it wedges a nameless sink into the listing forever. This makes the handler stricter: a severity or partition given as a number, a bool, or null was previously coerced and is now rejected. The commandline builds both fields from argv via asString(), so they are always strings there and the parser is unaffected. Also drop the second isMember(partition) test, which was unconditionally true because the preceding branch already returned, along with the unreachable return it guarded. No behavior change. Add a LogLevel test suite, which did not exist; the RPCCall cases cover only the commandline-to-JSON parse and never reach the handler. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The entry was added with a placeholder because the pull request did not exist when the fix was committed. Point it at XRPLF#7922. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
High Level Overview of Change
Fixes #6751
doLogLevelread both of its parameters with an unguardedasString(). This addsisString()guards toseverityandpartitionso malformed values returninvalidParamsinstead of a genericinternalerror, and rejects the empty partitionname. Adds a
LogLevelRPC test suite, which did not previously exist.Context of Change
json::Value::asString()throwsjson::Errorfor arrays and objects, and silentlystringifies every scalar (
Int->"42",Boolean->"true",Null->""). Thethrow was swallowed by
callMethod's catch-all, so a malformed value produced a genericinternalerror rather thaninvalidParams, and the request was recorded as a serverfault in the perf log.
The two parameters were broken to different degrees:
severitywas only half broken. A coerced scalar still failedLogs::fromStringand came back as
invalidParams, so the outcome was accidentally correct; only arraysand objects misbehaved.
partitionhad no downstream validation at all, andLogs::getdoes anemplace,so it creates the sink on demand. A coerced value therefore permanently added a
partition literally named
42,1.500000,trueor""to the map, andpartitionSeverities()then reported it in every subsequentlog_levelresponse.The empty partition name is rejected for the same reason the type check exists:
""isnot a partition anyone can have meant, and accepting it wedges a nameless sink into the
listing forever.
This makes the handler stricter. A
severityorpartitiongiven as a number, a bool,or
nullwas previously coerced and is now rejected. The commandline is unaffected:RPCParser::parseLogLevelbuilds both fields fromargvviaasString(), so they arealways strings on that path.
Also drops the second
isMember(jss::partition)test, which was unconditionally truebecause the preceding branch already returned, along with the unreachable
return rpcError(RpcInvalidParams);it guarded. No behavior change.This is the same class of defect, in the same admin handler tree, as the
blacklistthresholdandget_countsmin_countfixes, and follows their shape.API Impact
log_levelis admin-only, so the affected surface is small. The change is filed underBugfixes in
API-CHANGELOG.md, consistent with theblacklistandget_countsentriesfor the same class of fix.
libxrplchange (any change that may affectlibxrplor dependents oflibxrpl)Before / After
{"severity": ["array"]}internalinvalidParams{"severity": 42}invalidParamsinvalidParams(unchanged){"severity": "warn", "partition": 42}42invalidParams{"severity": "warn", "partition": null}""invalidParams{"severity": "warn", "partition": ""}""invalidParams{"severity": "warn", "partition": {}}internalinvalidParamsTest Plan
New suite
xrpl.rpc.LogLevel(src/test/rpc/LogLevel_test.cpp), 5 cases / 84assertions, modelled on
BlackList_test.cpp. There was no handler-level test forlog_levelbefore this; the existingRPCCall_testcases cover only thecommandline-to-JSON parse and never reach the handler.
Coverage: the levels listing; every alias
Logs::fromStringaccepts and the nameLogs::toStringreports back; thebase/ mixed-caseBASEdistinction; and therejected-value tables for both parameters. The invalid-partition case additionally
asserts that none of
42,1.500000,trueor""appear as partition names in thelisting afterwards — that assertion is what pins the sink-map pollution.
Verified the suite fails against the unpatched handler: 18 failures, including all four
sink-pollution assertions, confirming those partitions were really being created.
Future Tasks
The
API-CHANGELOG.mdentry uses an#NNNNplaceholder and needs a follow-up commitpointing it at this PR number.