From d4d8be1e2757cefaf114b8c98b962bea63966667 Mon Sep 17 00:00:00 2001 From: kilnerm <38245247+kilnerm@users.noreply.github.com> Date: Mon, 24 Dec 2018 10:35:55 +0000 Subject: [PATCH] Convert parameter data to utf8, ensure string is terminated (#79) --- .../PostgreSQLConnection.swift | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/Sources/SwiftKueryPostgreSQL/PostgreSQLConnection.swift b/Sources/SwiftKueryPostgreSQL/PostgreSQLConnection.swift index d908b15..b6891ca 100644 --- a/Sources/SwiftKueryPostgreSQL/PostgreSQLConnection.swift +++ b/Sources/SwiftKueryPostgreSQL/PostgreSQLConnection.swift @@ -403,16 +403,34 @@ public class PostgreSQLConnection: Connection { return } - var parameterPointers = [UnsafeMutablePointer?]() + var parameterPointers = [UnsafeMutablePointer?]() var parameterData = [UnsafePointer?]() + + // Reserve capacity of pointers, otherwise it may cause performance issues + if parameters.count > 0 { + parameterPointers.reserveCapacity(parameters.count) + parameterData.reserveCapacity(parameters.count) + } + // At the moment we only create string parameters. Binary parameters should be added. for parameter in parameters { if let parameter = parameter { let parameterString = String(describing: parameter) let count = parameterString.lengthOfBytes(using: .utf8) + 1 - parameterPointers.append(UnsafeMutablePointer.allocate(capacity: Int(count))) - memcpy(parameterPointers[parameterPointers.count-1]!, UnsafeRawPointer(parameterString), count) - parameterData.append(parameterPointers.last!) + // Convert the string value to a UTF8 string, we cannot rely on UnsafeRawPointer(String) to return a UTF8 string that is null terminated so explicitly terminate it. + guard let parameterUTF8_data = parameterString.data(using: .utf8) else { + return onCompletion(.error(QueryError.syntaxError("Could not convert parameter to UTF8 string"))) + } + // Allocate memory + let parameter_pointer = UnsafeMutablePointer.allocate(capacity: count) + parameterUTF8_data.copyBytes(to: parameter_pointer, count: count-1) + // Force null termination of C UTF8 string + parameter_pointer[count-1] = 0 + // parameterPointers will be used later to free memory + parameterPointers.append(parameter_pointer) + parameter_pointer.withMemoryRebound(to: Int8.self, capacity: count) { parameter_pointer in + parameterData.append(parameter_pointer) + } } else { parameterData.append(nil)