compiler API: final cleanups; improve security by diabling 'gorge' and friends

This commit is contained in:
Andreas Rumpf 2018-05-29 09:07:24 +02:00
commit 688c54d8f1
9 changed files with 55 additions and 28 deletions

View file

@ -9,6 +9,9 @@
# implements the command dispatcher and several commands # implements the command dispatcher and several commands
when not defined(nimcore):
{.error: "nimcore MUST be defined for Nim's core tooling".}
import import
llstream, strutils, ast, astalgo, lexer, syntaxes, renderer, options, msgs, llstream, strutils, ast, astalgo, lexer, syntaxes, renderer, options, msgs,
os, condsyms, rodread, rodwrite, times, os, condsyms, rodread, rodwrite, times,

View file

@ -5,6 +5,7 @@ path:"llvm"
path:"$projectPath/.." path:"$projectPath/.."
define:booting define:booting
define:nimcore
#import:"$projectpath/testability" #import:"$projectpath/testability"
@if windows: @if windows:
@ -13,6 +14,5 @@ define:booting
define:useStdoutAsStdmsg define:useStdoutAsStdmsg
cs:partial
#define:useNodeIds #define:useNodeIds
#gc:markAndSweep #gc:markAndSweep

View file

@ -29,7 +29,7 @@ iterator exportedSymbols*(i: Interpreter): PSym =
s = nextIter(it, i.mainModule.tab) s = nextIter(it, i.mainModule.tab)
proc selectUniqueSymbol*(i: Interpreter; name: string; proc selectUniqueSymbol*(i: Interpreter; name: string;
symKinds: set[TSymKind]): PSym = symKinds: set[TSymKind] = {skLet, skVar}): PSym =
## Can be used to access a unique symbol of ``name`` and ## Can be used to access a unique symbol of ``name`` and
## the given ``symKinds`` filter. ## the given ``symKinds`` filter.
assert i != nil assert i != nil
@ -55,8 +55,11 @@ proc callRoutine*(i: Interpreter; routine: PSym; args: openArray[PNode]): PNode
assert i != nil assert i != nil
result = vm.execProc(PCtx i.graph.vm, routine, args) result = vm.execProc(PCtx i.graph.vm, routine, args)
proc declareRoutine*(i: Interpreter; pkg, module, name: string; proc getGlobalValue*(i: Interpreter; letOrVar: PSym): PNode =
impl: proc (a: VmArgs) {.closure, gcsafe.}) = result = vm.getGlobalValue(PCtx i.graph.vm, letOrVar)
proc implementRoutine*(i: Interpreter; pkg, module, name: string;
impl: proc (a: VmArgs) {.closure, gcsafe.}) =
assert i != nil assert i != nil
let vm = PCtx(i.graph.vm) let vm = PCtx(i.graph.vm)
vm.registerCallback(pkg & "." & module & "." & name, impl) vm.registerCallback(pkg & "." & module & "." & name, impl)

View file

@ -972,7 +972,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
when hasFFI: when hasFFI:
let prcValue = c.globals.sons[prc.position-1] let prcValue = c.globals.sons[prc.position-1]
if prcValue.kind == nkEmpty: if prcValue.kind == nkEmpty:
globalError(c.config, c.debug[pc], "canot run " & prc.name.s) globalError(c.config, c.debug[pc], "cannot run " & prc.name.s)
let newValue = callForeignFunction(prcValue, prc.typ, tos.slots, let newValue = callForeignFunction(prcValue, prc.typ, tos.slots,
rb+1, rc-1, c.debug[pc]) rb+1, rc-1, c.debug[pc])
if newValue.kind != nkEmpty: if newValue.kind != nkEmpty:
@ -1336,14 +1336,17 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].node.strVal = opSlurp(regs[rb].node.strVal, c.debug[pc], regs[ra].node.strVal = opSlurp(regs[rb].node.strVal, c.debug[pc],
c.module, c.config) c.module, c.config)
of opcGorge: of opcGorge:
decodeBC(rkNode) when defined(nimcore):
inc pc decodeBC(rkNode)
let rd = c.code[pc].regA inc pc
let rd = c.code[pc].regA
createStr regs[ra] createStr regs[ra]
regs[ra].node.strVal = opGorge(regs[rb].node.strVal, regs[ra].node.strVal = opGorge(regs[rb].node.strVal,
regs[rc].node.strVal, regs[rd].node.strVal, regs[rc].node.strVal, regs[rd].node.strVal,
c.debug[pc], c.config)[0] c.debug[pc], c.config)[0]
else:
globalError(c.config, c.debug[pc], "VM is not built with 'gorge' support")
of opcNError: of opcNError:
decodeB(rkNode) decodeB(rkNode)
let a = regs[ra].node let a = regs[ra].node

View file

@ -107,15 +107,16 @@ proc registerAdditionalOps*(c: PCtx) =
wrap1f_math(ceil) wrap1f_math(ceil)
wrap2f_math(fmod) wrap2f_math(fmod)
wrap2s(getEnv, ospathsop) when defined(nimcore):
wrap1s(existsEnv, ospathsop) wrap2s(getEnv, ospathsop)
wrap2svoid(putEnv, ospathsop) wrap1s(existsEnv, ospathsop)
wrap1s(dirExists, osop) wrap2svoid(putEnv, ospathsop)
wrap1s(fileExists, osop) wrap1s(dirExists, osop)
wrap2svoid(writeFile, systemop) wrap1s(fileExists, osop)
wrap1s(readFile, systemop) wrap2svoid(writeFile, systemop)
systemop getCurrentExceptionMsg wrap1s(readFile, systemop)
registerCallback c, "stdlib.*.staticWalkDir", proc (a: VmArgs) {.nimcall.} = systemop getCurrentExceptionMsg
setResult(a, staticWalkDirImpl(getString(a, 0), getBool(a, 1))) registerCallback c, "stdlib.*.staticWalkDir", proc (a: VmArgs) {.nimcall.} =
systemop gorgeEx setResult(a, staticWalkDirImpl(getString(a, 0), getBool(a, 1)))
systemop gorgeEx
macrosop getProjectPath macrosop getProjectPath

View file

@ -9,6 +9,9 @@
## Nimsuggest is a tool that helps to give editors IDE like capabilities. ## Nimsuggest is a tool that helps to give editors IDE like capabilities.
when not defined(nimcore):
{.error: "nimcore MUST be defined for Nim's core tooling".}
import strutils, os, parseopt, parseutils, sequtils, net, rdstdin, sexp import strutils, os, parseopt, parseutils, sequtils, net, rdstdin, sexp
# Do NOT import suggest. It will lead to wierd bugs with # Do NOT import suggest. It will lead to wierd bugs with
# suggestionResultHook, because suggest.nim is included by sigmatch. # suggestionResultHook, because suggest.nim is included by sigmatch.
@ -486,9 +489,9 @@ var
proc mainCommand(graph: ModuleGraph; cache: IdentCache) = proc mainCommand(graph: ModuleGraph; cache: IdentCache) =
let conf = graph.config let conf = graph.config
clearPasses() clearPasses(graph)
registerPass verbosePass registerPass graph, verbosePass
registerPass semPass registerPass graph, semPass
conf.cmd = cmdIdeTools conf.cmd = cmdIdeTools
incl conf.globalOptions, optCaasEnabled incl conf.globalOptions, optCaasEnabled
wantMainModule(conf) wantMainModule(conf)

View file

@ -8,6 +8,8 @@ path:"$lib/packages/docutils"
define:useStdoutAsStdmsg define:useStdoutAsStdmsg
define:nimsuggest define:nimsuggest
define:nimcore
# die when nimsuggest uses more than 4GB: # die when nimsuggest uses more than 4GB:
@if cpu32: @if cpu32:
define:"nimMaxHeap=2000" define:"nimMaxHeap=2000"
@ -15,7 +17,6 @@ define:nimsuggest
define:"nimMaxHeap=4000" define:"nimMaxHeap=4000"
@end @end
#cs:partial
#define:useNodeIds #define:useNodeIds
#define:booting #define:booting
#define:noDocgen #define:noDocgen

View file

@ -5,3 +5,5 @@ echo "top level statements are executed!"
proc hostProgramRunsThis*(a, b: float): float = proc hostProgramRunsThis*(a, b: float): float =
result = addFloats(a, b, 1.0) result = addFloats(a, b, 1.0)
let hostProgramWantsThis* = "my secret"

View file

@ -1,6 +1,7 @@
discard """ discard """
output: '''top level statements are executed! output: '''top level statements are executed!
2.0 2.0
my secret
''' '''
""" """
@ -16,7 +17,7 @@ proc main() =
quit "cannot find Nim's standard library" quit "cannot find Nim's standard library"
var intr = createInterpreter("myscript.nim", [std, getAppDir()]) var intr = createInterpreter("myscript.nim", [std, getAppDir()])
intr.declareRoutine("*", "exposed", "addFloats", proc (a: VmArgs) = intr.implementRoutine("*", "exposed", "addFloats", proc (a: VmArgs) =
setResult(a, getFloat(a, 0) + getFloat(a, 1) + getFloat(a, 2)) setResult(a, getFloat(a, 0) + getFloat(a, 1) + getFloat(a, 2))
) )
@ -31,6 +32,16 @@ proc main() =
echo res.floatVal echo res.floatVal
else: else:
echo "bug!" echo "bug!"
let foreignValue = selectUniqueSymbol(intr, "hostProgramWantsThis")
if foreignValue == nil:
quit "script does not export a global of the name: hostProgramWantsThis"
let val = intr.getGlobalValue(foreignValue)
if val.kind in {nkStrLit..nkTripleStrLit}:
echo val.strVal
else:
echo "bug!"
destroyInterpreter(intr) destroyInterpreter(intr)
main() main()