Skip to content

Fix crash in getShortCallsign on all-slash callsigns (ArrayIndexOutOfBoundsException) - #509

Merged
patrickrb merged 2 commits into
devfrom
optio/task-13cb3022-cb26-45e1-bc22-06e7b195f33f
Jul 9, 2026
Merged

Fix crash in getShortCallsign on all-slash callsigns (ArrayIndexOutOfBoundsException)#509
patrickrb merged 2 commits into
devfrom
optio/task-13cb3022-cb26-45e1-bc22-06e7b195f33f

Conversation

@patrickrb

Copy link
Copy Markdown
Owner

Root cause

GeneralVariables.getShortCallsign(String) splits a compound callsign on /
and returns the longest segment:

String[] temp = callsign.split("/");
...
return temp[max_index];   // max_index defaults to 0

For an all-slash input ("/", "//", "///") Java's String.split
strips trailing empty tokens and returns a zero-length array, so
temp[0] throws ArrayIndexOutOfBoundsException. String.contains("/") is
true for these inputs, so the guarded branch is entered and the crash fires.

Impact

getShortCallsign is only ever called on the operator's own callsign, but
that value is loaded from persisted config and used on real threads:

  • DatabaseOpr ReadConfig.doInBackground (startup config load, background
    thread) — getShortCallsign(myCallsign) when the stored callsign contains
    /. An uncaught exception here crashes the app on startup, and because
    the value is persisted the crash recurs on every launch.
  • GeneralVariables.checkIsMyCallsign(...) calls getShortCallsign(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 into
a 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]:

String[] temp = callsign.split("/");
if (temp.length == 0) {
    return callsign;
}

Behavior is unchanged for every well-formed input — plain callsigns
(W1AW), prefix/suffix compounds (DL/W1AW, W1AW/P, W1AW/QRP), and
leading-slash forms (/W1AW) all return exactly what they did before.

Testing

  • New GeneralVariablesShortCallsignTest (JUnit4 + Truth, Robolectric because
    GeneralVariables carries Android LiveData statics) covers plain,
    compound, leading-slash, and the all-slash regression cases. The all-slash
    case fails with ArrayIndexOutOfBoundsException before the fix and passes
    after.
  • ./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

…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

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 23.57%. Comparing base (66575b9) to head (f2e4495).
⚠️ Report is 4 commits behind head on dev.

Additional details and impacted files

Impacted file tree graph

@@            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           
Flag Coverage Δ
android 13.26% <ø> (ø)
native 9.93% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 == 0 guard in getShortCallsign to avoid ArrayIndexOutOfBoundsException and 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.

Comment thread ft8af/app/src/test/java/com/k1af/ft8af/GeneralVariablesShortCallsignTest.java Outdated
"the method unconditionally read" -> "reads".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@patrickrb
patrickrb merged commit 6fad8eb into dev Jul 9, 2026
17 checks passed
@patrickrb
patrickrb deleted the optio/task-13cb3022-cb26-45e1-bc22-06e7b195f33f branch July 9, 2026 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants