kotlin:S2116 reports false positive for ByteArray.toString(Charsets.UTF_8)

Then tell us:

  • kotlin (2.0.21)
  • kotlin:S2116
  • The suggested fix is incorrect for ByteArray.toString(Charsets.UTF_8) as the output is changed dramatically. ByteArray.toString(Charsets.UTF_8) returns the ByteArray inputted to a String(bytearray, charset). Your suggested fix to use ByteArray.contentToString() instead returns the bytearray integers as singular items. This is a breaking change with very different results. Please refer to the code snippet for details :slight_smile:
  • Are you using
    • SonarQube Enterprise Edition v2025.1.4 (113907)
    • SonarQube for IDE 11.2.0.82481
  • How can we reproduce the problem? Give us a self-contained snippet of code
val byteArray = "Test".toByteArray(Charsets.UTF_8)
val toStringWithCharset = byteArray.toString(Charsets.UTF_8) // "Test"
val contentToString = byteArray.contentToString() // "[84, 101, 115, 116]"
println("toStringWithCharset $toStringWithCharset")
println("contentToString $contentToString")

Hi Swen,

Thanks for reaching out. I agree with you and as it happens, the S2116 implementation already accounts for this exception.

Typically, when we see such issues, it boils down to the analyzer missing some semantic information and the compiler incorrectly resolving a function call as a result. Which command and configuration are you using to analyze your project?

Meanwhile, we have also created a ticket to improve the fallback behavior when semantic is incomplete. However, by providing full semantics to your analysis, the analysis will become more reliable and valuable overall, besides also fixing this particular issue.

Hi Johann,

thank you for your feedback, but I am not sure how I can provide semantics. As far as I can tell our config should automatically locate all relevant files :slight_smile:
The project is a multimodule for kotlin android.

We are use gradle with the plugin “org.sonarqube“ in version 6.3.1.5724.

Our properties are as list below:

sonar {
    properties {
        property("sonar.host.url", "<hostUrl>")
        property("sonar.projectKey", "<projectKey>")
        property("sonar.projectName", "<projectName>")
        property("sonar.projectVersion", AndroidConfig.versionName)
        property("sonar.scanner.skipJreProvisioning", true)
        property("sonar.gradle.skipCompile", true)
        property("sonar.gradle.scanAll", true)
        property("sonar.cpd.exclusions", "**/assets/*.html")
        property("sonar.androidLint.reportPaths", fileList("**/build/reports/lint-results-*.xml"))
        property("sonar.junit.reportPaths", dirList("**/build/test-results/"))
        property("sonar.kotlin.detekt.reportPaths", fileList("**/build/reports/detekt/detekt.xml"))
        property("sonar.kotlin.ktlint.reportPaths", fileList("**/build/reports/ktlint/**/ktlint*Check.xml"))
        property("sonar.java.checkstyle.reportPaths", fileList("**/build/reports/unusedNavDestinations.xml"))
    }
}

Best regards,

Swen

Hi Swen,

Normally, the Gradle Sonar plugin should handle the semantics for you. Is it possible that you are not compiling the project before running the Sonar task?

I’ve been trying to reproduce the problem based on the configuration and code snippet you have provided but have not been successful so far. Could you create a small but complete reproducer that we can execute directly to analyze further? You can provide a link to a repository in this thread.

1 Like

Hi Johan,
you are right - we only used the command ./gradlew sonar.
We are doing compile and checks beforehand, so I thought we could skip this with the sonar command.
Using instead ./gradlew build sonar fixes the issue :slight_smile:
Thanks for your support!