vapor / mysql-nio

🐬 Non-blocking, event-driven Swift client for MySQL.
MIT License
87 stars 28 forks source link

Fix crash when parsing timestamps with microsecond text #101

Open wlsdms0122 opened 8 months ago

wlsdms0122 commented 8 months ago

Crash occurred even parsing logic enhanced by #72.

When you get rows from the simple query with TIMESTAMP column like this.

id ... created_at
1 ... 1970-01-01 00:00:01.000000

Application crashed at MySQLData.swift:459 due to forced unwrapping of time with a value of nil.

457:            ...
458:            case .datetime, .timestamp:
450:                return (self.time!.date ?? Date(timeIntervalSince1970: 0)).description

If we follow the logic of the MySQLTime conversion of TIMESTAMP text to MySQLTime, we can find that point of crash.

public init?(_ string: String) {
    ...    
    guard parts.count >= 6,
          let year = UInt16(parts[0]),
          let month = UInt16(parts[1]),
          let day = UInt16(parts[2]),
          let hour = UInt16(parts[3]),
          let minute = UInt16(parts[4]),
          let second = UInt16(parts[5]) // <- `parts[5]` is "01.000000" actually. Conversion to `UInt16` fails because of microseconds.
    else {
        return nil
    }
    ...
}

So we added code to parse the real number text correctly.

0xTim commented 3 months ago

@wlsdms0122 I'll leave @gwynne to do the actual review but can you add a test to show it not crashing? Thanks!

wlsdms0122 commented 2 months ago

@0xTim I added a test case. The main branch doesn't pass it.