Fix CodeQL note-severity alerts: shadowed locals, and the array cases of the debug formatter - #848
Merged
vharseko merged 1 commit intoAug 5, 2026
Conversation
…he debug formatter CodeQL java/local-shadows-field and java/chained-type-tests. Seven locals carried the name of a field in scope: the two collections TopologyMsg decodes before assigning them to the fields, the address family PatternIP.evaluate() computes for the remote address and compares against the rule's, the three labels NewGroupPanel lays out next to the field holding four, the Throwable a catch clause hid from the Runnable reporting through it, the per-operation connection of a worker thread, and a message built in a catch block. All are renamed after what they hold; no reference changes meaning. DebugMessageFormatter dispatched over eight array types to seven decorateArrayArg() overloads with identical bodies, and short[] was not among them - such an argument reached the log undecorated, as [S@6d06d69c. A single method walking the array through java.lang.reflect.Array replaces all seven and covers every component type. Object[] keeps its branch since its elements are decorated in turn. The class had no tests; DebugMessageFormatterTest now covers each array type, nested maps, lists and object arrays, and the concatenation fallback taken when the format string does not match its arguments. The remaining fifteen type-test chains dispatch over operations, replication messages, SDK requests, JAAS callbacks, generated JAXB and configuration types: none can grow a visitor without breaking an API, and none of them tests a subtype after its supertype.
maximthomas
approved these changes
Aug 4, 2026
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.
Addresses the seven
java/local-shadows-fieldalerts and thejava/chained-type-testsgroup. The one chain which was not dispatch over a fixed API turned out to be missing a case.Locals which shadow the field they are about to fill, or the field next to them (7)
TopologyMsg— the decoding constructor buildsreplicaInfosandrsInfosin locals of exactly those names, then assigns the fields from them. The locals becomenewReplicaInfosandnewRsInfos, sothis.is no longer what tells the two apart.PatternIP.evaluate()— the localipTypeholds the address family of the remote address and is compared against the field, which holds the family of the rule:if (ipType != this.ipType). The local is nowremoteIpTypeand the comparison readsremoteIpType != ipType.NewGroupPanel.createLayout()— the localJLabel[] labelsholds the three labels being laid out, while the field of the same name holds four and is whatsetText()walks later. The local becomeslayoutLabels.BrowseEntriesPanel— the readerRunnablereports its outcome through a fieldt, and the surroundingcatch (Throwable t)shadowed it. The catch parameter is nowth, matching the inner catch a few lines above.PerformanceRunner.WorkerThread.run()— the localconnectionis the connection used for one operation, the field is the connection the thread was given (null when it must borrow one per operation). The local becomesconnectionToUse, which also removes the need forthis.inif (this.connection == null).AggregationPropertyDefinition— in thecatchblock a localmessageshadowed the field of the same name that thetryblock adds to the unacceptable reasons. It becomeserrorMessage.None of these change behaviour: every reference already resolved to what the code intended, which is why they are alerts about names rather than bugs.
The one type-test chain worth collapsing — and the type it had forgotten
DebugMessageFormatter.decorateArg()tested forObject[]and then for each primitive array type in turn, dispatching to sevendecorateArrayArg()overloads whose bodies were byte-for-byte identical.short[]was missing from the chain, so ashort[]argument was never decorated and a debug log line showed[S@6d06d69cinstead of its contents.The seven overloads become one method taking
Objectand walking the array throughjava.lang.reflect.Array, which covers every component type including the forgotten one.Object[]keeps its own branch, because its elements are decorated recursively and the elements of a primitive array never need that. The chain goes from ten type tests to three.DebugMessageFormatterhad no tests. The newDebugMessageFormatterTestpins the formatting of each array type, of nested maps, lists and object arrays, and of the fallback taken when the format string does not match its arguments — 13 cases.The other 15 chains, left as they are
They all dispatch over a closed family of types owned by an API which cannot grow a visitor:
SdkConnectionAdapter,HTTPClientConnection,BoundedWorkQueueStrategydispatch overAbandonOperation…UnbindOperation.ServerReaderandReplicationDomaindispatch overReplicationMsgsubtypes.Requests.copyOfRequest()(21 tests),Connections, andAuthRatedispatch over the publicRequesthierarchy; adding anaccept(RequestVisitor)to it is an API break.SASLBindClientImpl.handle(Callback[])dispatches overjavax.security.auth.callbacktypes, which are third-party.DSMLServlet.performLDAPRequest()dispatches over the DSML request classes, which are generated from the schema.ConfigFromConnection,ConfigFromFile,BrowseSchemaPanelandSchemaElementComboBoxCellRendererdispatch over the generated*Cfg/*CfgClientinterfaces and over the SDK schema elements.MonitorData.add()picks a syntax from the runtime class of a monitor value, relying oninstanceofmatching subclasses (IntegerthroughNumber), which a class-keyed map would not do.While reading them I checked each chain for the failure this alert often hides — a subtype tested after its supertype, which makes the later branch dead. There is none: in
ServerReader, the types tested afterRoutableMsg(ResetGenerationIdMsg,WindowProbeMsg,TopologyMsg,ChangeStatusMsg,ChangeTimeHeartbeatMsg,StopMsg) all extendReplicationMsgdirectly, and inMonitorDatatheNumbersubclasses are tested beforeNumber. Every chain either ends in anelseor falls through to a documented result.Testing
opendj-config547 tests (coveringAggregationPropertyDefinition) andopendj-ldap-toolkit291 tests (coveringPerformanceRunner) — all passing.opendj-server-legacy(-Pprecommit):SynchronizationMsgTest(75),ProtocolCompatibilityTest(58) andModifyDNMsgTest(5) encode and decodeTopologyMsgacross protocol versions,IPTestCase(58) covers the IP bind rules ofPatternIP, andDebugMessageFormatterTest(13) withDebugLogPublisherTest(6) cover the formatter — 215 tests, all passing.