muter-mutation-testing / muter

🔎 Automated mutation testing for Swift 🕳️
MIT License
491 stars 39 forks source link

[Error]Swift/StringCharacterView.swift:158 Fatal error: String index is out of bounds #257

Closed KyosukeKotani closed 3 months ago

KyosukeKotani commented 7 months ago

Hello. When I ran Muter, the following error occurred. If anyone knows the solution, please let me know.

Error Message

Analyzing source files to find mutants which can be inserted into your project...
Swift/StringCharacterView.swift:158 Fatal error: String index is out of bounds
zsh: trace trap  muter run

Summay

Target

ex.return activeFlag && !isNew()

The above code has been confirmed not to produce any errors by commenting it out.

Environment

※Using a translation tool to translate Japanese to English.

ZevEisenberg commented 7 months ago

Hi @KyosukeKotani, and thanks for taking the time to write in! Would you be able to provide a sample project that reproduces the issue?

KyosukeKotani commented 7 months ago

@ZevEisenberg Thank you for your reply. I am unable to provide the code where the error occurred immediately as it is a product code. I will try to reproduce this issue in a sample project. Please wait a few days.

KyosukeKotani commented 7 months ago

@ZevEisenberg Thank you for your patience. We are unable to provide a sample project, but we have identified the cause of the error and provide a sample file.

Sample File

//
//  sample_mutation.swift
//  sample-project
//

import Foundation

public final class SampleError: NSObject, NSCoding {
    public func encode(with coder: NSCoder) {
        <#code#>
    }

    public init?(coder: NSCoder) {
        <#code#>
    }
    public let text: String

    public let viewCount: Int
    public let activationFlag: Bool

    public init?(dictionary: [String: Any]) {
        guard
            let text = dictionary["Text"] as? String,
            let activationFlag = dictionary["ActivationFlag"] as? Bool,
            let viewCount = dictionary["ViewCounts"] as? Int,
            !text.isEmpty else {
            return nil
        }

        self.text = text
        self.viewCount = viewCount
        self.activationFlag = activationFlag
    }

    public func isDiscarded() -> Bool {

        if viewCount > 0 {
            return true
        }

        return false
    }

    public func isEnabledToShow() -> Bool {
        // バルーンの表示判定
        return activationFlag && !isDiscarded()
    }
}

Error Cause

// バルーンの表示判定

I have confirmed that deleting the above comment will prevent the error from occurring.

ZevEisenberg commented 7 months ago

Just to clarify - is the original comment in Japanese? If you replace the comment with English, does that fix the error? I'm wondering if this is a problem with how we are parsing multi-byte characters.

KyosukeKotani commented 7 months ago

Yes, it is. The original comment is in Japanese. Replacing the Japanese with English fixes the error. I too have a feeling that there is a problem with how we are parsing multi-byte characters.

hoangatuan commented 4 months ago
Screenshot 2024-02-24 at 10 00 55 PM

The problem lies at the line 74. The nodePosition here is UTF-8 offset, but later we treat it as character offset at line 77. If we use alphabet character, utf-8 offset will equal to character offset since we only need 1 byte for alphabet character. For non-alphabet character, it uses multi-byte => utf-8 offset is not equal to character offset => Crash

hoangatuan commented 4 months ago

@rakaramos @ZevEisenberg I've raised a PR to fix this issue here: https://github.com/muter-mutation-testing/muter/pull/270 Please help to review it when you have time 🙏