summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2014-02-22 10:50:22 +0100
committerAndreas Rumpf <rumpf_a@web.de>2014-02-22 10:50:22 +0100
commited4f2f5e4df46a5795b3007f59192b8a1104fc1e (patch)
tree264b5615254a366facf704a929921f1cf1979107 /compiler
parentb89c8df35e13c0be0252c17fddbadab4a5135ff4 (diff)
parent3aa7f65240005a7d5ce26519248fa435f3ed3e5b (diff)
downloadNim-ed4f2f5e4df46a5795b3007f59192b8a1104fc1e.tar.gz
Merge pull request #947 from gradha/pr_checks_bad_exported_symbols_800
Checks that exported symbols are valid C identifiers. Refs #800.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/pragmas.nim23
1 files changed, 20 insertions, 3 deletions
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index d9ed50cfe..75c16f6cd 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -97,8 +97,25 @@ proc makeExternImport(s: PSym, extname: string) =
   incl(s.flags, sfImportc)
   excl(s.flags, sfForward)
 
-proc makeExternExport(s: PSym, extname: string) = 
+const invalidIdentChars = AllChars - IdentChars
+
+proc validateExternCName(s: PSym, info: TLineInfo) =
+  ## Validates that the symbol name in s.loc.r is a valid C identifier.
+  ##
+  ## Valid identifiers are those alphanumeric including the underscore not
+  ## starting with a number. If the check fails, a generic error will be
+  ## displayed to the user.
+  let target = ropeToStr(s.loc.r)
+  if target.len < 1 or (not (target[0] in IdentStartChars)) or
+      (not target.allCharsInSet(IdentChars)):
+    localError(info, errGenerated, "invalid exported symbol")
+
+proc makeExternExport(s: PSym, extname: string, info: TLineInfo) =
   setExternName(s, extname)
+  case gCmd
+  of cmdCompileToC, cmdCompileToCpp, cmdCompileToOC:
+    validateExternCName(s, info)
+  else: discard
   incl(s.flags, sfExportc)
 
 proc processImportCompilerProc(s: PSym, extname: string) =
@@ -515,7 +532,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
       if k in validPragmas: 
         case k
         of wExportc: 
-          makeExternExport(sym, getOptionalStr(c, it, "$1"))
+          makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info)
           incl(sym.flags, sfUsed) # avoid wrong hints
         of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1"))
         of wImportCompilerProc:
@@ -601,7 +618,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
           processDynLib(c, it, sym)
         of wCompilerproc: 
           noVal(it)           # compilerproc may not get a string!
-          makeExternExport(sym, "$1")
+          makeExternExport(sym, "$1", it.info)
           incl(sym.flags, sfCompilerProc)
           incl(sym.flags, sfUsed) # suppress all those stupid warnings
           registerCompilerProc(sym)