From e8657c7107761fae7a8b5559df3b88165c238a12 Mon Sep 17 00:00:00 2001 From: ee7 <45465154+ee7@users.noreply.github.com> Date: Fri, 19 Aug 2022 21:40:53 +0200 Subject: make implicit cstring conversions explicit (#19488) The Nim manual says that an implicit conversion to cstring will eventually not be allowed [1]: A Nim `string` is implicitly convertible to `cstring` for convenience. [...] Even though the conversion is implicit, it is not *safe*: The garbage collector does not consider a `cstring` to be a root and may collect the underlying memory. For this reason, the implicit conversion will be removed in future releases of the Nim compiler. Certain idioms like conversion of a `const` string to `cstring` are safe and will remain to be allowed. And from Nim 1.6.0, such a conversion triggers a warning [2]: A dangerous implicit conversion to `cstring` now triggers a `[CStringConv]` warning. This warning will become an error in future versions! Use an explicit conversion like `cstring(x)` in order to silence the warning. However, some files in this repo produced such a warning. For example, before this commit, compiling `parsejson.nim` would produce: /foo/Nim/lib/pure/parsejson.nim(221, 37) Warning: implicit conversion to 'cstring' from a non-const location: my.buf; this will become a compile time error in the future [CStringConv] /foo/Nim/lib/pure/parsejson.nim(231, 39) Warning: implicit conversion to 'cstring' from a non-const location: my.buf; this will become a compile time error in the future [CStringConv] This commit resolves the most visible `CStringConv` warnings, making the cstring conversions explicit. [1] https://github.com/nim-lang/Nim/blob/d2318d9ccfe6/doc/manual.md#cstring-type [2] https://github.com/nim-lang/Nim/blob/d2318d9ccfe6/changelogs/changelog_1_6_0.md#type-system --- lib/impure/db_mysql.nim | 10 +++++----- lib/impure/db_odbc.nim | 2 +- lib/impure/db_postgres.nim | 24 ++++++++++++------------ lib/impure/db_sqlite.nim | 6 +++--- lib/nimhcr.nim | 14 +++++++------- lib/pure/logging.nim | 2 +- lib/pure/nativesockets.nim | 6 +++--- lib/pure/net.nim | 2 +- lib/pure/os.nim | 20 ++++++++++---------- lib/pure/osproc.nim | 10 +++++----- lib/pure/parsejson.nim | 4 ++-- 11 files changed, 50 insertions(+), 50 deletions(-) (limited to 'lib') diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim index 562847e6b..223c5dcf8 100644 --- a/lib/impure/db_mysql.nim +++ b/lib/impure/db_mysql.nim @@ -149,17 +149,17 @@ proc tryExec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): bool {. tags: [ReadDbEffect, WriteDbEffect].} = ## tries to execute the query and returns true if successful, false otherwise. var q = dbFormat(query, args) - return mysql.real_query(PMySQL db, q, q.len) == 0'i32 + return mysql.real_query(PMySQL db, q.cstring, q.len) == 0'i32 proc rawExec(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) = var q = dbFormat(query, args) - if mysql.real_query(PMySQL db, q, q.len) != 0'i32: dbError(db) + if mysql.real_query(PMySQL db, q.cstring, q.len) != 0'i32: dbError(db) proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) {. tags: [ReadDbEffect, WriteDbEffect].} = ## executes the query and raises EDB if not successful. var q = dbFormat(query, args) - if mysql.real_query(PMySQL db, q, q.len) != 0'i32: dbError(db) + if mysql.real_query(PMySQL db, q.cstring, q.len) != 0'i32: dbError(db) proc newRow(L: int): Row = newSeq(result, L) @@ -360,7 +360,7 @@ proc tryInsertId*(db: DbConn, query: SqlQuery, ## executes the query (typically "INSERT") and returns the ## generated ID for the row or -1 in case of an error. var q = dbFormat(query, args) - if mysql.real_query(PMySQL db, q, q.len) != 0'i32: + if mysql.real_query(PMySQL db, q.cstring, q.len) != 0'i32: result = -1'i64 else: result = mysql.insertId(PMySQL db) @@ -409,7 +409,7 @@ proc open*(connection, user, password, database: string): DbConn {. else: substr(connection, 0, colonPos-1) port: int32 = if colonPos < 0: 0'i32 else: substr(connection, colonPos+1).parseInt.int32 - if mysql.realConnect(res, host, user, password, database, + if mysql.realConnect(res, host.cstring, user, password, database, port, nil, 0) == nil: var errmsg = $mysql.error(res) mysql.close(res) diff --git a/lib/impure/db_odbc.nim b/lib/impure/db_odbc.nim index 1e4032b34..0ecd8129f 100644 --- a/lib/impure/db_odbc.nim +++ b/lib/impure/db_odbc.nim @@ -334,7 +334,7 @@ proc `[]`*(row: InstantRow, col: int): string {.inline.} = proc unsafeColumnAt*(row: InstantRow, index: int): cstring {.inline.} = ## Return cstring of given column of the row - row.row[index] + row.row[index].cstring proc len*(row: InstantRow): int {.inline.} = ## Returns number of columns in the row diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim index 36e035d3d..82403ab00 100644 --- a/lib/impure/db_postgres.nim +++ b/lib/impure/db_postgres.nim @@ -133,7 +133,7 @@ proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string = proc tryExec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): bool {.tags: [ReadDbEffect, WriteDbEffect].} = ## tries to execute the query and returns true if successful, false otherwise. - var res = pqexecParams(db, dbFormat(query, args), 0, nil, nil, + var res = pqexecParams(db, dbFormat(query, args).cstring, 0, nil, nil, nil, nil, 0) result = pqresultStatus(res) == PGRES_COMMAND_OK pqclear(res) @@ -143,7 +143,7 @@ proc tryExec*(db: DbConn, stmtName: SqlPrepared, ReadDbEffect, WriteDbEffect].} = ## tries to execute the query and returns true if successful, false otherwise. var arr = allocCStringArray(args) - var res = pqexecPrepared(db, stmtName.string, int32(args.len), arr, + var res = pqexecPrepared(db, stmtName.cstring, int32(args.len), arr, nil, nil, 0) deallocCStringArray(arr) result = pqresultStatus(res) == PGRES_COMMAND_OK @@ -152,7 +152,7 @@ proc tryExec*(db: DbConn, stmtName: SqlPrepared, proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) {. tags: [ReadDbEffect, WriteDbEffect].} = ## executes the query and raises EDB if not successful. - var res = pqexecParams(db, dbFormat(query, args), 0, nil, nil, + var res = pqexecParams(db, dbFormat(query, args).cstring, 0, nil, nil, nil, nil, 0) if pqresultStatus(res) != PGRES_COMMAND_OK: dbError(db) pqclear(res) @@ -160,7 +160,7 @@ proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) {. proc exec*(db: DbConn, stmtName: SqlPrepared, args: varargs[string]) {.tags: [ReadDbEffect, WriteDbEffect].} = var arr = allocCStringArray(args) - var res = pqexecPrepared(db, stmtName.string, int32(args.len), arr, + var res = pqexecPrepared(db, stmtName.cstring, int32(args.len), arr, nil, nil, 0) deallocCStringArray(arr) if pqResultStatus(res) != PGRES_COMMAND_OK: dbError(db) @@ -172,20 +172,20 @@ proc newRow(L: int): Row = proc setupQuery(db: DbConn, query: SqlQuery, args: varargs[string]): PPGresult = - result = pqexec(db, dbFormat(query, args)) + result = pqexec(db, dbFormat(query, args).cstring) if pqResultStatus(result) != PGRES_TUPLES_OK: dbError(db) proc setupQuery(db: DbConn, stmtName: SqlPrepared, args: varargs[string]): PPGresult = var arr = allocCStringArray(args) - result = pqexecPrepared(db, stmtName.string, int32(args.len), arr, + result = pqexecPrepared(db, stmtName.cstring, int32(args.len), arr, nil, nil, 0) deallocCStringArray(arr) if pqResultStatus(result) != PGRES_TUPLES_OK: dbError(db) proc setupSingeRowQuery(db: DbConn, query: SqlQuery, args: varargs[string]) = - if pqsendquery(db, dbFormat(query, args)) != 1: + if pqsendquery(db, dbFormat(query, args).cstring) != 1: dbError(db) if pqSetSingleRowMode(db) != 1: dbError(db) @@ -193,7 +193,7 @@ proc setupSingeRowQuery(db: DbConn, query: SqlQuery, proc setupSingeRowQuery(db: DbConn, stmtName: SqlPrepared, args: varargs[string]) = var arr = allocCStringArray(args) - if pqsendqueryprepared(db, stmtName.string, int32(args.len), arr, nil, nil, 0) != 1: + if pqsendqueryprepared(db, stmtName.cstring, int32(args.len), arr, nil, nil, 0) != 1: dbError(db) if pqSetSingleRowMode(db) != 1: dbError(db) @@ -205,7 +205,7 @@ proc prepare*(db: DbConn; stmtName: string, query: SqlQuery; ## via `$1`, `$2`, `$3`, etc. if nParams > 0 and not string(query).contains("$1"): dbError("parameter substitution expects \"$1\"") - var res = pqprepare(db, stmtName, query.string, int32(nParams), nil) + var res = pqprepare(db, stmtName, query.cstring, int32(nParams), nil) if pqResultStatus(res) != PGRES_COMMAND_OK: dbError(db) return SqlPrepared(stmtName) @@ -590,7 +590,7 @@ proc execAffectedRows*(db: DbConn, query: SqlQuery, ## executes the query (typically "UPDATE") and returns the ## number of affected rows. var q = dbFormat(query, args) - var res = pqExec(db, q) + var res = pqExec(db, q.cstring) if pqresultStatus(res) != PGRES_COMMAND_OK: dbError(db) result = parseBiggestInt($pqcmdTuples(res)) pqclear(res) @@ -601,7 +601,7 @@ proc execAffectedRows*(db: DbConn, stmtName: SqlPrepared, ## executes the query (typically "UPDATE") and returns the ## number of affected rows. var arr = allocCStringArray(args) - var res = pqexecPrepared(db, stmtName.string, int32(args.len), arr, + var res = pqexecPrepared(db, stmtName.cstring, int32(args.len), arr, nil, nil, 0) deallocCStringArray(arr) if pqresultStatus(res) != PGRES_COMMAND_OK: dbError(db) @@ -634,7 +634,7 @@ proc open*(connection, user, password, database: string): DbConn {. else: substr(connection, 0, colonPos-1) port = if colonPos < 0: "" else: substr(connection, colonPos+1) - result = pqsetdbLogin(host, port, nil, nil, database, user, password) + result = pqsetdbLogin(host.cstring, port.cstring, nil, nil, database, user, password) if pqStatus(result) != CONNECTION_OK: dbError(result) # result = nil proc setEncoding*(connection: DbConn, encoding: string): bool {. diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim index 1638d38c6..f79e87f1b 100644 --- a/lib/impure/db_sqlite.nim +++ b/lib/impure/db_sqlite.nim @@ -235,7 +235,7 @@ proc tryExec*(db: DbConn, query: SqlQuery, assert(not db.isNil, "Database not connected.") var q = dbFormat(query, args) var stmt: sqlite3.PStmt - if prepare_v2(db, q, q.len.cint, stmt, nil) == SQLITE_OK: + if prepare_v2(db, q.cstring, q.len.cint, stmt, nil) == SQLITE_OK: let x = step(stmt) if x in {SQLITE_DONE, SQLITE_ROW}: result = finalize(stmt) == SQLITE_OK @@ -278,7 +278,7 @@ proc setupQuery(db: DbConn, query: SqlQuery, args: varargs[string]): PStmt = assert(not db.isNil, "Database not connected.") var q = dbFormat(query, args) - if prepare_v2(db, q, q.len.cint, result, nil) != SQLITE_OK: dbError(db) + if prepare_v2(db, q.cstring, q.len.cint, result, nil) != SQLITE_OK: dbError(db) proc setupQuery(db: DbConn, stmtName: SqlPrepared): SqlPrepared {.since: (1, 3).} = assert(not db.isNil, "Database not connected.") @@ -653,7 +653,7 @@ proc tryInsertID*(db: DbConn, query: SqlQuery, var q = dbFormat(query, args) var stmt: sqlite3.PStmt result = -1 - if prepare_v2(db, q, q.len.cint, stmt, nil) == SQLITE_OK: + if prepare_v2(db, q.cstring, q.len.cint, stmt, nil) == SQLITE_OK: if step(stmt) == SQLITE_DONE: result = last_insert_rowid(db) if finalize(stmt) != SQLITE_OK: diff --git a/lib/nimhcr.nim b/lib/nimhcr.nim index 2846f931b..b35ecf8df 100644 --- a/lib/nimhcr.nim +++ b/lib/nimhcr.nim @@ -487,7 +487,7 @@ when defined(createNimHcr): recursiveDiscovery(modules[curr].imports) allModulesOrderedByDFS.add(curr) continue - loadDll(curr) + loadDll(curr.cstring) # first load all dependencies of the current module and init it after that recursiveDiscovery(modules[curr].imports) @@ -497,20 +497,20 @@ when defined(createNimHcr): proc initModules() = # first init the pointers to hcr functions and also do the registering of typeinfo globals for curr in modulesToInit: - initHcrData(curr) - initTypeInfoGlobals(curr) + initHcrData(curr.cstring) + initTypeInfoGlobals(curr.cstring) # for now system always gets fully inited before any other module (including when reloading) - initPointerData(system) - initGlobalScope(system) + initPointerData(system.cstring) + initGlobalScope(system.cstring) # proceed with the DatInit calls - for all modules - including the main one! for curr in allModulesOrderedByDFS: if curr != system: - initPointerData(curr) + initPointerData(curr.cstring) mainDatInit() # execute top-level code (in global scope) for curr in modulesToInit: if curr != system: - initGlobalScope(curr) + initGlobalScope(curr.cstring) # cleanup old symbols which are gone now for curr in modulesToInit: cleanupSymbols(curr) diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim index 6751a372a..cbe8a827a 100644 --- a/lib/pure/logging.nim +++ b/lib/pure/logging.nim @@ -367,7 +367,7 @@ method log*(logger: ConsoleLogger, level: Level, args: varargs[string, `$`]) = if level >= logging.level and level >= logger.levelThreshold: let ln = substituteLog(logger.fmtStr, level, args) when defined(js): - let cln: cstring = ln + let cln = ln.cstring case level of lvlDebug: {.emit: "console.debug(`cln`);".} of lvlInfo: {.emit: "console.info(`cln`);".} diff --git a/lib/pure/nativesockets.nim b/lib/pure/nativesockets.nim index 39438a04e..ca4e61621 100644 --- a/lib/pure/nativesockets.nim +++ b/lib/pure/nativesockets.nim @@ -300,7 +300,7 @@ proc getAddrInfo*(address: string, port: Port, domain: Domain = AF_INET, if domain == AF_INET6: hints.ai_flags = AI_V4MAPPED let socketPort = if sockType == SOCK_RAW: "" else: $port - var gaiResult = getaddrinfo(address, socketPort, addr(hints), result) + var gaiResult = getaddrinfo(address, socketPort.cstring, addr(hints), result) if gaiResult != 0'i32: when useWinVersion or defined(freertos): raiseOSError(osLastError()) @@ -460,10 +460,10 @@ when not useNimNetLite: const size = 256 result = newString(size) when useWinVersion: - let success = winlean.gethostname(result, size) + let success = winlean.gethostname(result.cstring, size) else: # Posix - let success = posix.gethostname(result, size) + let success = posix.gethostname(result.cstring, size) if success != 0.cint: raiseOSError(osLastError()) let x = len(cstring(result)) diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 370b83e54..7b50b8ba6 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -682,7 +682,7 @@ when defineSsl: var found = false let useEnvVars = (if verifyMode == CVerifyPeerUseEnvVars: true else: false) for fn in scanSSLCertificates(useEnvVars = useEnvVars): - if newCTX.SSL_CTX_load_verify_locations(fn, nil) == VerifySuccess: + if newCTX.SSL_CTX_load_verify_locations(fn.cstring, nil) == VerifySuccess: found = true break if not found: diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 79f9950a7..82ccd9051 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1259,12 +1259,12 @@ proc findExe*(exe: string, followSymlinks: bool = true; while followSymlinks: # doubles as if here if x.symlinkExists: var r = newString(maxSymlinkLen) - var len = readlink(x, r, maxSymlinkLen) + var len = readlink(x.cstring, r.cstring, maxSymlinkLen) if len < 0: raiseOSError(osLastError(), exe) if len > maxSymlinkLen: r = newString(len+1) - len = readlink(x, r, len) + len = readlink(x.cstring, r.cstring, len) setLen(r, len) if isAbsolute(r): x = r @@ -1404,8 +1404,8 @@ when not defined(nimscript): var bufsize = 1024 # should be enough result = newString(bufsize) while true: - if getcwd(result, bufsize) != nil: - setLen(result, c_strlen(result)) + if getcwd(result.cstring, bufsize) != nil: + setLen(result, c_strlen(result.cstring)) break else: let err = osLastError() @@ -1774,12 +1774,12 @@ proc expandSymlink*(symlinkPath: string): string {.noWeirdTarget.} = result = symlinkPath else: result = newString(maxSymlinkLen) - var len = readlink(symlinkPath, result, maxSymlinkLen) + var len = readlink(symlinkPath, result.cstring, maxSymlinkLen) if len < 0: raiseOSError(osLastError(), symlinkPath) if len > maxSymlinkLen: result = newString(len+1) - len = readlink(symlinkPath, result, len) + len = readlink(symlinkPath, result.cstring, len) setLen(result, len) const hasCCopyfile = defined(osx) and not defined(nimLegacyCopyFile) @@ -2344,7 +2344,7 @@ iterator walkDir*(dir: string; relative = false, checkDir = false): var k = pcFile template kSetGeneric() = # pure Posix component `k` resolution - if lstat(path, s) < 0'i32: continue # don't yield + if lstat(path.cstring, s) < 0'i32: continue # don't yield elif S_ISDIR(s.st_mode): k = pcDir elif S_ISLNK(s.st_mode): @@ -3041,10 +3041,10 @@ when not weirdTarget and (defined(freebsd) or defined(dragonfly) or defined(netb when not weirdTarget and (defined(linux) or defined(solaris) or defined(bsd) or defined(aix)): proc getApplAux(procPath: string): string = result = newString(maxSymlinkLen) - var len = readlink(procPath, result, maxSymlinkLen) + var len = readlink(procPath, result.cstring, maxSymlinkLen) if len > maxSymlinkLen: result = newString(len+1) - len = readlink(procPath, result, len) + len = readlink(procPath, result.cstring, len) setLen(result, len) when not weirdTarget and defined(openbsd): @@ -3169,7 +3169,7 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect], noW var size = cuint32(0) getExecPath1(nil, size) result = newString(int(size)) - if getExecPath2(result, size): + if getExecPath2(result.cstring, size): result = "" # error! if result.len > 0: result = result.expandFilename diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 666ccdda8..a0079cf95 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -1086,9 +1086,9 @@ elif not defined(useNimRtl): var pid: Pid if (poUsePath in data.options): - res = posix_spawnp(pid, data.sysCommand, fops, attr, data.sysArgs, data.sysEnv) + res = posix_spawnp(pid, data.sysCommand.cstring, fops, attr, data.sysArgs, data.sysEnv) else: - res = posix_spawn(pid, data.sysCommand, fops, attr, data.sysArgs, data.sysEnv) + res = posix_spawn(pid, data.sysCommand.cstring, fops, attr, data.sysArgs, data.sysEnv) discard posix_spawn_file_actions_destroy(fops) discard posix_spawnattr_destroy(attr) @@ -1174,14 +1174,14 @@ elif not defined(useNimRtl): when defined(uClibc) or defined(linux) or defined(haiku): # uClibc environment (OpenWrt included) doesn't have the full execvpe let exe = findExe(data.sysCommand) - discard execve(exe, data.sysArgs, data.sysEnv) + discard execve(exe.cstring, data.sysArgs, data.sysEnv) else: # MacOSX doesn't have execvpe, so we need workaround. # On MacOSX we can arrive here only from fork, so this is safe: environ = data.sysEnv - discard execvp(data.sysCommand, data.sysArgs) + discard execvp(data.sysCommand.cstring, data.sysArgs) else: - discard execve(data.sysCommand, data.sysArgs, data.sysEnv) + discard execve(data.sysCommand.cstring, data.sysArgs, data.sysEnv) startProcessFail(data) {.pop.} diff --git a/lib/pure/parsejson.nim b/lib/pure/parsejson.nim index c92eac26e..fcbcf8e36 100644 --- a/lib/pure/parsejson.nim +++ b/lib/pure/parsejson.nim @@ -221,7 +221,7 @@ proc parseString(my: var JsonParser): TokKind = add(my.a, 'u') inc(pos, 2) var pos2 = pos - var r = parseEscapedUTF16(my.buf, pos) + var r = parseEscapedUTF16(cstring(my.buf), pos) if r < 0: my.err = errInvalidToken break @@ -231,7 +231,7 @@ proc parseString(my: var JsonParser): TokKind = my.err = errInvalidToken break inc(pos, 2) - var s = parseEscapedUTF16(my.buf, pos) + var s = parseEscapedUTF16(cstring(my.buf), pos) if (s and 0xfc00) == 0xdc00 and s > 0: r = 0x10000 + (((r - 0xd800) shl 10) or (s - 0xdc00)) else: -- cgit 1.4.1-2-gfad0