diff options
author | Araq <rumpf_a@web.de> | 2011-09-24 00:46:41 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-09-24 00:46:41 +0200 |
commit | 6023e994fbc949c77abbbe4ffae761ca982732db (patch) | |
tree | 1a2173755edc026cdbae89c7f5ca0bdfdc83a138 /lib | |
parent | 2359b8b1073cfd027ac14a147aba06cc18d61010 (diff) | |
download | Nim-6023e994fbc949c77abbbe4ffae761ca982732db.tar.gz |
beginning of a taint mode; type system enhancements
Diffstat (limited to 'lib')
-rwxr-xr-x | lib/core/macros.nim | 28 | ||||
-rwxr-xr-x | lib/pure/cgi.nim | 70 | ||||
-rwxr-xr-x | lib/pure/os.nim | 42 | ||||
-rwxr-xr-x | lib/pure/parseopt.nim | 2 | ||||
-rwxr-xr-x | lib/system.nim | 30 | ||||
-rwxr-xr-x | lib/system/sysio.nim | 6 |
6 files changed, 97 insertions, 81 deletions
diff --git a/lib/core/macros.nim b/lib/core/macros.nim index bebcab677..e362922c8 100755 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -36,15 +36,18 @@ type nnkMacroDef, nnkTemplateDef, nnkIteratorDef, nnkOfBranch, nnkElifBranch, nnkExceptBranch, nnkElse, nnkMacroStmt, nnkAsmStmt, nnkPragma, nnkIfStmt, nnkWhenStmt, - nnkForStmt, nnkWhileStmt, nnkCaseStmt, nnkVarSection, - nnkConstSection, nnkConstDef, nnkTypeSection, nnkTypeDef, + nnkForStmt, nnkWhileStmt, nnkCaseStmt, + nnkVarSection, nnkLetSection, nnkConstSection, + nnkConstDef, nnkTypeSection, nnkTypeDef, nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt, nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkDiscardStmt, nnkStmtList, nnkImportStmt, nnkFromStmt, nnkIncludeStmt, nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr, nnkStmtListType, nnkBlockType, nnkTypeOfExpr, nnkObjectTy, nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen, - nnkRefTy, nnkPtrTy, nnkVarTy, nnkDistinctTy, + nnkRefTy, nnkPtrTy, nnkVarTy, + nnkConstTy, nnkMutableTy, + nnkDistinctTy, nnkProcTy, nnkEnumTy, nnkEnumFieldDef, nnkReturnToken TNimNodeKinds* = set[TNimrodNodeKind] TNimrodTypeKind* = enum @@ -184,7 +187,7 @@ proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} = ## in a string literal node return newStrLitNode(repr(n)) -proc prettyPrint*(n: PNimrodNode): string {.compileTime.} = +proc toLisp*(n: PNimrodNode): string {.compileTime.} = ## Convert the AST `n` to a human-readable string ## ## You can use this as a tool to explore the Nimrod's abstract syntax @@ -204,10 +207,10 @@ proc prettyPrint*(n: PNimrodNode): string {.compileTime.} = of nnkIdent: add(result, $n.ident) of nnkSym, nnkNone: assert false else: - add(result, prettyPrint(n[0])) + add(result, toLisp(n[0])) for j in 1..n.len-1: add(result, ", ") - add(result, prettyPrint(n[j])) + add(result, toLisp(n[j])) add(result, ")") @@ -215,7 +218,7 @@ proc toYaml*(n: PNimrodNode): string {.magic: "AstToYaml".} ## Converts the AST `n` to an YAML string ## ## Provides more detailed, potentially harder to digest information - ## than `prettyPrint` + ## than `toLisp` proc parseExpr*(s: string) : expr {.magic: "ParseExprToAst".} ## Compiles the passed string to its AST representation @@ -226,10 +229,13 @@ proc parseStmt*(s: string) : stmt {.magic: "ParseStmtToAst".} ## Expects one or more statements proc getAst*(macroOrTemplate: expr): expr {.magic: "ExpandMacroToAst".} - ## Obtains the AST nodes returned from a macro or template invocation - ## example: - ## macro FooMacro() = - ## var ast = getAst(BarTemplate()) + ## Obtains the AST nodes returned from a macro or template invocation. + ## Example: + ## + ## .. code-block:: nimrod + ## + ## macro FooMacro() = + ## var ast = getAst(BarTemplate()) proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} = ## checks that `n` is of kind `k`. If this is not the case, diff --git a/lib/pure/cgi.nim b/lib/pure/cgi.nim index 47517ae98..c8536236d 100755 --- a/lib/pure/cgi.nim +++ b/lib/pure/cgi.nim @@ -107,7 +107,7 @@ proc cgiError*(msg: string) {.noreturn.} = raise e proc getEncodedData(allowedMethods: set[TRequestMethod]): string = - case getenv("REQUEST_METHOD") + case getenv("REQUEST_METHOD").string of "POST": if methodPost notin allowedMethods: cgiError("'REQUEST_METHOD' 'POST' is not supported") @@ -192,131 +192,131 @@ proc validateData*(data: PStringTable, validKeys: openarray[string]) = proc getContentLength*(): string = ## returns contents of the ``CONTENT_LENGTH`` environment variable - return getenv("CONTENT_LENGTH") + return getenv("CONTENT_LENGTH").string proc getContentType*(): string = ## returns contents of the ``CONTENT_TYPE`` environment variable - return getenv("CONTENT_Type") + return getenv("CONTENT_Type").string proc getDocumentRoot*(): string = ## returns contents of the ``DOCUMENT_ROOT`` environment variable - return getenv("DOCUMENT_ROOT") + return getenv("DOCUMENT_ROOT").string proc getGatewayInterface*(): string = ## returns contents of the ``GATEWAY_INTERFACE`` environment variable - return getenv("GATEWAY_INTERFACE") + return getenv("GATEWAY_INTERFACE").string proc getHttpAccept*(): string = ## returns contents of the ``HTTP_ACCEPT`` environment variable - return getenv("HTTP_ACCEPT") + return getenv("HTTP_ACCEPT").string proc getHttpAcceptCharset*(): string = ## returns contents of the ``HTTP_ACCEPT_CHARSET`` environment variable - return getenv("HTTP_ACCEPT_CHARSET") + return getenv("HTTP_ACCEPT_CHARSET").string proc getHttpAcceptEncoding*(): string = ## returns contents of the ``HTTP_ACCEPT_ENCODING`` environment variable - return getenv("HTTP_ACCEPT_ENCODING") + return getenv("HTTP_ACCEPT_ENCODING").string proc getHttpAcceptLanguage*(): string = ## returns contents of the ``HTTP_ACCEPT_LANGUAGE`` environment variable - return getenv("HTTP_ACCEPT_LANGUAGE") + return getenv("HTTP_ACCEPT_LANGUAGE").string proc getHttpConnection*(): string = ## returns contents of the ``HTTP_CONNECTION`` environment variable - return getenv("HTTP_CONNECTION") + return getenv("HTTP_CONNECTION").string proc getHttpCookie*(): string = ## returns contents of the ``HTTP_COOKIE`` environment variable - return getenv("HTTP_COOKIE") + return getenv("HTTP_COOKIE").string proc getHttpHost*(): string = ## returns contents of the ``HTTP_HOST`` environment variable - return getenv("HTTP_HOST") + return getenv("HTTP_HOST").string proc getHttpReferer*(): string = ## returns contents of the ``HTTP_REFERER`` environment variable - return getenv("HTTP_REFERER") + return getenv("HTTP_REFERER").string proc getHttpUserAgent*(): string = ## returns contents of the ``HTTP_USER_AGENT`` environment variable - return getenv("HTTP_USER_AGENT") + return getenv("HTTP_USER_AGENT").string proc getPathInfo*(): string = ## returns contents of the ``PATH_INFO`` environment variable - return getenv("PATH_INFO") + return getenv("PATH_INFO").string proc getPathTranslated*(): string = ## returns contents of the ``PATH_TRANSLATED`` environment variable - return getenv("PATH_TRANSLATED") + return getenv("PATH_TRANSLATED").string proc getQueryString*(): string = ## returns contents of the ``QUERY_STRING`` environment variable - return getenv("QUERY_STRING") + return getenv("QUERY_STRING").string proc getRemoteAddr*(): string = ## returns contents of the ``REMOTE_ADDR`` environment variable - return getenv("REMOTE_ADDR") + return getenv("REMOTE_ADDR").string proc getRemoteHost*(): string = ## returns contents of the ``REMOTE_HOST`` environment variable - return getenv("REMOTE_HOST") + return getenv("REMOTE_HOST").string proc getRemoteIdent*(): string = ## returns contents of the ``REMOTE_IDENT`` environment variable - return getenv("REMOTE_IDENT") + return getenv("REMOTE_IDENT").string proc getRemotePort*(): string = ## returns contents of the ``REMOTE_PORT`` environment variable - return getenv("REMOTE_PORT") + return getenv("REMOTE_PORT").string proc getRemoteUser*(): string = ## returns contents of the ``REMOTE_USER`` environment variable - return getenv("REMOTE_USER") + return getenv("REMOTE_USER").string proc getRequestMethod*(): string = ## returns contents of the ``REQUEST_METHOD`` environment variable - return getenv("REQUEST_METHOD") + return getenv("REQUEST_METHOD").string proc getRequestURI*(): string = ## returns contents of the ``REQUEST_URI`` environment variable - return getenv("REQUEST_URI") + return getenv("REQUEST_URI").string proc getScriptFilename*(): string = ## returns contents of the ``SCRIPT_FILENAME`` environment variable - return getenv("SCRIPT_FILENAME") + return getenv("SCRIPT_FILENAME").string proc getScriptName*(): string = ## returns contents of the ``SCRIPT_NAME`` environment variable - return getenv("SCRIPT_NAME") + return getenv("SCRIPT_NAME").string proc getServerAddr*(): string = ## returns contents of the ``SERVER_ADDR`` environment variable - return getenv("SERVER_ADDR") + return getenv("SERVER_ADDR").string proc getServerAdmin*(): string = ## returns contents of the ``SERVER_ADMIN`` environment variable - return getenv("SERVER_ADMIN") + return getenv("SERVER_ADMIN").string proc getServerName*(): string = ## returns contents of the ``SERVER_NAME`` environment variable - return getenv("SERVER_NAME") + return getenv("SERVER_NAME").string proc getServerPort*(): string = ## returns contents of the ``SERVER_PORT`` environment variable - return getenv("SERVER_PORT") + return getenv("SERVER_PORT").string proc getServerProtocol*(): string = ## returns contents of the ``SERVER_PROTOCOL`` environment variable - return getenv("SERVER_PROTOCOL") + return getenv("SERVER_PROTOCOL").string proc getServerSignature*(): string = ## returns contents of the ``SERVER_SIGNATURE`` environment variable - return getenv("SERVER_SIGNATURE") + return getenv("SERVER_SIGNATURE").string proc getServerSoftware*(): string = ## returns contents of the ``SERVER_SOFTWARE`` environment variable - return getenv("SERVER_SOFTWARE") + return getenv("SERVER_SOFTWARE").string proc setTestData*(keysvalues: openarray[string]) = ## fills the appropriate environment variables to test your CGI application. @@ -360,10 +360,10 @@ proc setCookie*(name, value: string) = var gcookies: PStringTable = nil -proc getCookie*(name: string): string = +proc getCookie*(name: string): TaintedString = ## Gets a cookie. If no cookie of `name` exists, "" is returned. if gcookies == nil: gcookies = parseCookies(getHttpCookie()) - result = gcookies[name] + result = TaintedString(gcookies[name]) proc existsCookie*(name: string): bool = ## Checks if a cookie of `name` exists. diff --git a/lib/pure/os.nim b/lib/pure/os.nim index ccbf98828..50c6ffeba 100755 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -692,7 +692,7 @@ proc findEnvVar(key: string): int = if startsWith(environment[i], temp): return i return -1 -proc getEnv*(key: string): string = +proc getEnv*(key: string): TaintedString = ## Returns the value of the `environment variable`:idx: named `key`. ## ## If the variable does not exist, "" is returned. To distinguish @@ -700,11 +700,11 @@ proc getEnv*(key: string): string = ## `existsEnv(key)`. var i = findEnvVar(key) if i >= 0: - return substr(environment[i], find(environment[i], '=')+1) + return TaintedString(substr(environment[i], find(environment[i], '=')+1)) else: var env = cgetenv(key) - if env == nil: return "" - result = $env + if env == nil: return TaintedString("") + result = TaintedString($env) proc existsEnv*(key: string): bool = ## Checks whether the environment variable named `key` exists. @@ -733,14 +733,15 @@ proc putEnv*(key, val: string) = if SetEnvironmentVariableA(key, val) == 0'i32: OSError() -iterator envPairs*(): tuple[key, value: string] = +iterator envPairs*(): tuple[key, value: TaintedString] = ## Iterate over all `environments variables`:idx:. In the first component ## of the tuple is the name of the current variable stored, in the second ## its value. getEnvVarsC() for i in 0..high(environment): var p = find(environment[i], '=') - yield (substr(environment[i], 0, p-1), substr(environment[i], p+1)) + yield (TaintedString(substr(environment[i], 0, p-1)), + TaintedString(substr(environment[i], p+1))) iterator walkFiles*(pattern: string): string = ## Iterate over all the files that match the `pattern`. On POSIX this uses @@ -1078,18 +1079,18 @@ proc exclFilePermissions*(filename: string, proc getHomeDir*(): string {.rtl, extern: "nos$1".} = ## Returns the home directory of the current user. - when defined(windows): return getEnv("USERPROFILE") & "\\" - else: return getEnv("HOME") & "/" + when defined(windows): return string(getEnv("USERPROFILE")) & "\\" + else: return string(getEnv("HOME")) & "/" proc getConfigDir*(): string {.rtl, extern: "nos$1".} = ## Returns the config directory of the current user for applications. - when defined(windows): return getEnv("APPDATA") & "\\" - else: return getEnv("HOME") & "/.config/" + when defined(windows): return string(getEnv("APPDATA")) & "\\" + else: return string(getEnv("HOME")) & "/.config/" proc getTempDir*(): string {.rtl, extern: "nos$1".} = ## Returns the temporary directory of the current user for applications to ## save temporary files in. - when defined(windows): return getEnv("TEMP") & "\\" + when defined(windows): return string(getEnv("TEMP")) & "\\" else: return "/tmp/" when defined(windows): @@ -1107,14 +1108,14 @@ when defined(windows): if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLineA()) result = ownArgv.len-1 - proc paramStr*(i: int): string {.rtl, extern: "nos$1".} = + proc paramStr*(i: int): TaintedString {.rtl, extern: "nos$1".} = ## Returns the `i`-th `command line argument`:idx: given to the ## application. ## ## `i` should be in the range `1..paramCount()`, else ## the `EOutOfIndex` exception is raised. if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLineA()) - return ownArgv[i] + return TaintedString(ownArgv[i]) elif not defined(createNimRtl): # On Posix, there is no portable way to get the command line from a DLL. @@ -1122,8 +1123,8 @@ elif not defined(createNimRtl): cmdCount {.importc: "cmdCount".}: cint cmdLine {.importc: "cmdLine".}: cstringArray - proc paramStr*(i: int): string = - if i < cmdCount and i >= 0: return $cmdLine[i] + proc paramStr*(i: int): TaintedString = + if i < cmdCount and i >= 0: return TaintedString($cmdLine[i]) raise newException(EInvalidIndex, "invalid index") proc paramCount*(): int = return cmdCount-1 @@ -1172,13 +1173,14 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1".} = result = "" # error! else: # little heuristic that may work on other POSIX-like systems: - result = getEnv("_") + result = string(getEnv("_")) if len(result) == 0: - result = ParamStr(0) # POSIX guaranties that this contains the executable - # as it has been executed by the calling process + result = string(ParamStr(0)) + # POSIX guaranties that this contains the executable + # as it has been executed by the calling process if len(result) > 0 and result[0] != DirSep: # not an absolute path? # iterate over any path in the $PATH environment variable - for p in split(getEnv("PATH"), {PathSep}): + for p in split(string(getEnv("PATH")), {PathSep}): var x = joinPath(p, result) if ExistsFile(x): return x @@ -1230,7 +1232,7 @@ proc findExe*(exe: string): string = ## is added an ``.exe`` file extension if it has no extension. result = addFileExt(exe, os.exeExt) if ExistsFile(result): return - var path = os.getEnv("PATH") + var path = string(os.getEnv("PATH")) for candidate in split(path, pathSep): var x = candidate / result if ExistsFile(x): return x diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim index 1981c9242..347871bac 100755 --- a/lib/pure/parseopt.nim +++ b/lib/pure/parseopt.nim @@ -48,7 +48,7 @@ when defined(os.ParamCount): else: result.cmd = "" for i in countup(1, ParamCount()): - result.cmd = result.cmd & quoteIfContainsWhite(paramStr(i)) & ' ' + result.cmd = result.cmd & quoteIfContainsWhite(paramStr(i).string) & ' ' result.kind = cmdEnd result.key = "" result.val = "" diff --git a/lib/system.nim b/lib/system.nim index ea004b925..8e4205189 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -787,6 +787,19 @@ proc compileOption*(option, arg: string): bool {. const hasThreadSupport = compileOption("threads") hasSharedHeap = defined(boehmgc) # don't share heaps; every thread has its own +# taintMode = compileOption("taintmode") + +when defined(taintMode): + # XXX use a compile time option for it! + type TaintedString* = distinct string ## a distinct string type that + ## is `tainted`:idx:. It is an alias for + ## ``string`` if the taint mode is not + ## turned on. Use the ``-d:taintMode`` + ## command line switch to turn the taint + ## mode on. +else: + type TaintedString* = string + when hasThreadSupport: {.pragma: rtlThreadVar, threadvar.} @@ -896,11 +909,6 @@ type # these work for most platforms: PInt64* = ptr Int64 ## an alias for ``ptr int64`` PInt32* = ptr Int32 ## an alias for ``ptr int32`` -type TOptional*[T] = object - case hasValue* : bool - of true: value*: T - of false: nil - proc toFloat*(i: int): float {. magic: "ToFloat", noSideEffect, importc: "toFloat".} ## converts an integer `i` into a ``float``. If the conversion @@ -1653,7 +1661,7 @@ when not defined(EcmaScript) and not defined(NimrodVM): proc FlushFile*(f: TFile) {.importc: "fflush", noDecl.} ## Flushes `f`'s buffer. - proc readFile*(filename: string): string + proc readFile*(filename: string): TaintedString ## Opens a file named `filename` for reading. Then reads the ## file's content completely into a string and ## closes the file afterwards. Returns the string. @@ -1675,7 +1683,7 @@ when not defined(EcmaScript) and not defined(NimrodVM): proc write*(f: TFile, a: openArray[string]) ## Writes a value to the file `f`. May throw an IO exception. - proc readLine*(f: TFile): string + proc readLine*(f: TFile): TaintedString ## reads a line of text from the file `f`. May throw an IO exception. ## A line of text may be delimited by ``CR``, ``LF`` or ## ``CRLF``. The newline character(s) are not part of the returned string. @@ -1814,22 +1822,22 @@ when not defined(EcmaScript) and not defined(NimrodVM): when hasThreadSupport: include "system/channels" - iterator lines*(filename: string): string = + iterator lines*(filename: string): TaintedString = ## Iterate over any line in the file named `filename`. ## If the file does not exist `EIO` is raised. var f = open(filename) var res = "" while not endOfFile(f): rawReadLine(f, res) - yield res + yield TaintedString(res) Close(f) - iterator lines*(f: TFile): string = + iterator lines*(f: TFile): TaintedString = ## Iterate over any line in the file `f`. var res = "" while not endOfFile(f): rawReadLine(f, res) - yield res + yield TaintedString(res) include "system/assign" include "system/repr" diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index d48e87ae2..56815c0c5 100755 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -55,8 +55,8 @@ proc rawReadLine(f: TFile, result: var string) = break add result, chr(int(c)) -proc readLine(f: TFile): string = - result = "" +proc readLine(f: TFile): TaintedString = + result = TaintedString("") rawReadLine(f, result) proc write(f: TFile, i: int) = @@ -81,7 +81,7 @@ proc write(f: TFile, c: Char) = putc(c, f) proc write(f: TFile, a: openArray[string]) = for x in items(a): write(f, x) -proc readFile(filename: string): string = +proc readFile(filename: string): TaintedString = var f = open(filename) try: var len = getFileSize(f) |