Skip to content

Commit de72b79

Browse files
committed
Fix unaligned memory access and stability issues in FreeTDS integration
1 parent f4d7b45 commit de72b79

File tree

2 files changed

+18
-12
lines changed

2 files changed

+18
-12
lines changed

Sources/SQLClientSwift/SQLClient.swift

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,11 @@ public struct SQLRow: Sendable {
8888

8989
public var columns: [String] { storage.map(\.key) }
9090

91-
public subscript(column: String) -> Any? {
91+
public subscript(column: String) -> Sendable? {
9292
storage.first(where: { $0.key == column })?.value
9393
}
9494

95-
public subscript(index: Int) -> Any? {
95+
public subscript(index: Int) -> Sendable? {
9696
guard index >= 0 && index < storage.count else { return nil }
9797
return storage[index].value
9898
}
@@ -109,7 +109,11 @@ public struct SQLRow: Sendable {
109109
public func isNull(_ column: String) -> Bool { self[column] is NSNull }
110110

111111
public func toDictionary() -> [String: Any] {
112-
Dictionary(uniqueKeysWithValues: storage)
112+
var dict: [String: Any] = [:]
113+
for item in storage {
114+
dict[item.key] = item.value
115+
}
116+
return dict
113117
}
114118
}
115119

@@ -314,7 +318,6 @@ public actor SQLClient {
314318
private nonisolated func _disconnectSync(login: TDSHandle?, connection: TDSHandle?) {
315319
if let c = connection?.pointer { dbclose(c) }
316320
if let l = login?.pointer { dbloginfree(l) }
317-
dbexit()
318321
}
319322

320323
private nonisolated func _executeSync(sql: String, connection: TDSHandle, maxTextSize: Int) throws -> SQLClientResult {
@@ -346,7 +349,11 @@ public actor SQLClient {
346349
colMeta.append((name: name, type: type))
347350
columnTypes[name] = type
348351
}
349-
while dbnextrow(conn) != NO_MORE_ROWS {
352+
while true {
353+
let rowCode = dbnextrow(conn)
354+
if rowCode == NO_MORE_ROWS || rowCode == FAIL { break }
355+
if rowCode == BUF_FULL { continue }
356+
350357
var storage: [(key: String, value: Sendable)] = []
351358
for (idx, col) in colMeta.enumerated() {
352359
let colIdx = Int32(idx + 1)
@@ -372,15 +379,15 @@ public actor SQLClient {
372379
case 48: // SYBINT1
373380
return NSNumber(value: data.load(as: UInt8.self))
374381
case 52: // SYBINT2
375-
return NSNumber(value: data.load(as: Int16.self))
382+
return NSNumber(value: data.loadUnaligned(as: Int16.self))
376383
case 56: // SYBINT4
377-
return NSNumber(value: data.load(as: Int32.self))
384+
return NSNumber(value: data.loadUnaligned(as: Int32.self))
378385
case 127: // SYBINT8
379-
return NSNumber(value: data.load(as: Int64.self))
386+
return NSNumber(value: data.loadUnaligned(as: Int64.self))
380387
case 59: // SYBREAL
381-
return NSNumber(value: data.load(as: Float.self))
388+
return NSNumber(value: data.loadUnaligned(as: Float.self))
382389
case 62: // SYBFLT8
383-
return NSNumber(value: data.load(as: Double.self))
390+
return NSNumber(value: data.loadUnaligned(as: Double.self))
384391
case 50, 104: // SYBBIT, SYBBITN
385392
return NSNumber(value: data.load(as: UInt8.self) != 0)
386393
case 47, 39, 102, 103, 35, 99, 241: // SYBCHAR, SYBVARCHAR, SYBTEXT, SYBNTEXT, SYBXML, SYBNCHAR, SYBNVARCHAR

Sources/SQLClientSwift/SQLDataTable.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,7 @@ extension SQLClientResult {
383383
guard let raw = sqlRow[col.name] else { return .null }
384384
// If we have FreeTDS type for this row/column, use it
385385
if let tdsType = sqlRow.columnTypes[col.name] {
386-
let val: Sendable = raw as AnyObject
387-
return SQLCellValue.from(raw: val, freeTDSType: tdsType)
386+
return SQLCellValue.from(raw: raw, freeTDSType: tdsType)
388387
}
389388
return cellValueFromAny(raw, columnType: col.type)
390389
}

0 commit comments

Comments
 (0)