Fix crash in getShortCallsign on all-slash callsigns (ArrayIndexOutOfBoundsException) - #509
Merged
Merged
Conversation
…callsigns
getShortCallsign(String) split the callsign on '/' and unconditionally
returned temp[max_index]. For an all-slash input ('/', '//', ...) Java's
String.split strips trailing empty tokens and returns a zero-length array,
so temp[0] threw ArrayIndexOutOfBoundsException.
This is reached with the operator's own persisted callsign on the config
load background thread (DatabaseOpr ReadConfig) and on every decode cycle
via checkIsMyCallsign(...), turning a stray-slash callsign into an uncaught
crash that recurs on every launch. Fall back to the original string when
there is no usable segment.
Adds GeneralVariablesShortCallsignTest covering plain, compound, leading
slash, and the all-slash regression cases.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #509 +/- ##
=========================================
Coverage 23.57% 23.57%
Complexity 162 162
=========================================
Files 168 168
Lines 21628 21628
Branches 3154 3154
=========================================
Hits 5098 5098
Misses 16337 16337
Partials 193 193
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Fixes a startup/decode-thread crash in GeneralVariables.getShortCallsign(String) when the operator callsign is an all-slash string (e.g. "/", "//"), by guarding against Java’s String.split("/") returning a zero-length array on that input.
Changes:
- Add a
temp.length == 0guard ingetShortCallsignto avoidArrayIndexOutOfBoundsExceptionand fall back to the original callsign. - Add a Robolectric JUnit test covering plain, compound, leading-slash, and all-slash regression cases.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| ft8af/app/src/main/java/com/k1af/ft8af/GeneralVariables.java | Adds a defensive check for all-slash inputs before indexing the split array. |
| ft8af/app/src/test/java/com/k1af/ft8af/GeneralVariablesShortCallsignTest.java | Introduces regression/unit coverage for getShortCallsign, including the all-slash crash case. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
"the method unconditionally read" -> "reads". Co-Authored-By: Claude Opus 4.8 (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.
Root cause
GeneralVariables.getShortCallsign(String)splits a compound callsign on/and returns the longest segment:
For an all-slash input (
"/","//","///") Java'sString.splitstrips trailing empty tokens and returns a zero-length array, so
temp[0]throwsArrayIndexOutOfBoundsException.String.contains("/")istrue for these inputs, so the guarded branch is entered and the crash fires.
Impact
getShortCallsignis only ever called on the operator's own callsign, butthat value is loaded from persisted config and used on real threads:
DatabaseOprReadConfig.doInBackground(startup config load, backgroundthread) —
getShortCallsign(myCallsign)when the stored callsign contains/. An uncaught exception here crashes the app on startup, and becausethe value is persisted the crash recurs on every launch.
GeneralVariables.checkIsMyCallsign(...)callsgetShortCallsign(myCallsign)and runs on the decode thread for matching, so a stray-slash callsign
also crashes each decode cycle.
A single stray
/typed into (or migrated into) the callsign field turns intoa hard, recurring crash rather than being tolerated.
Fix
Fall back to the original string when the split yields no usable segment,
instead of indexing
temp[0]:Behavior is unchanged for every well-formed input — plain callsigns
(
W1AW), prefix/suffix compounds (DL/W1AW,W1AW/P,W1AW/QRP), andleading-slash forms (
/W1AW) all return exactly what they did before.Testing
GeneralVariablesShortCallsignTest(JUnit4 + Truth, Robolectric becauseGeneralVariablescarries AndroidLiveDatastatics) covers plain,compound, leading-slash, and the all-slash regression cases. The all-slash
case fails with
ArrayIndexOutOfBoundsExceptionbefore the fix and passesafter.
./gradlew :app:testDebugUnitTest— full suite green../gradlew :app:assembleDebug— APK builds.Risk
Minimal. One localized guard on a pathological input; no protocol, DSP, or
threading behavior changes, and all normal callsign shapes are unaffected.
🤖 Generated with Claude Code