made anchor resolution during deserialization safer

This commit is contained in:
Felix Krause 2020-11-10 14:48:19 +01:00
parent aa65c066d5
commit 4305bccbf0
4 changed files with 11 additions and 18 deletions

View File

@ -211,7 +211,7 @@ suite "Lexer":
pl("bar baz"), dirE(), i(0), pl("derp"), e()) pl("bar baz"), dirE(), i(0), pl("derp"), e())
test "Sequence with compact maps": test "Sequence with compact maps":
assertEquals("""- a: drzw\n- b""", i(0), ss(), pl("a"), mv(), pl("drzw"), i(0), ss(), pl("b"), e()) assertEquals("- a: drzw\n- b", i(0), si(), pl("a"), mv(), pl("drzw"), i(0), si(), pl("b"), e())
test "Empty lines": test "Empty lines":
assertEquals("""block: foo assertEquals("""block: foo

View File

@ -272,14 +272,3 @@ proc `$`*(event: Event): string {.raises: [].} =
of ssFolded: result &= " >" of ssFolded: result &= " >"
result &= yamlTestSuiteEscape(event.scalarContent) result &= yamlTestSuiteEscape(event.scalarContent)
of yamlAlias: result = "=ALI *" & $event.aliasTarget of yamlAlias: result = "=ALI *" & $event.aliasTarget
type
TypeID* = int ## unique ID of a type
var nextTypeID {.compileTime.}: TypeID
proc typeID*(T:typedesc): TypeID =
const id = nextTypeID
static:
inc nextTypeID
return id

View File

@ -138,7 +138,7 @@ proc composeNode(s: var YamlStream, tagLib: TagLibrary,
template addAnchor(c: ConstructionContext, target: Anchor) = template addAnchor(c: ConstructionContext, target: Anchor) =
if target != yAnchorNone: if target != yAnchorNone:
yAssert(not c.refs.hasKey(target)) yAssert(not c.refs.hasKey(target))
c.refs[target] = (id: typeID(YamlNode), p: cast[pointer](result)) c.refs[target] = (tag: yamlTag(YamlNode), p: cast[pointer](result))
var start: Event var start: Event
shallowCopy(start, s.next()) shallowCopy(start, s.next())

View File

@ -32,7 +32,7 @@ type
ConstructionContext* = ref object ConstructionContext* = ref object
## Context information for the process of constructing Nim values from YAML. ## Context information for the process of constructing Nim values from YAML.
refs*: Table[Anchor, tuple[id: TypeID, p: pointer]] refs*: Table[Anchor, tuple[tag: Tag, p: pointer]]
YamlConstructionError* = object of YamlLoadingError YamlConstructionError* = object of YamlLoadingError
## Exception that may be raised when constructing data objects from a ## Exception that may be raised when constructing data objects from a
@ -86,7 +86,7 @@ proc representChild*[O](value: O, ts: TagStyle, c: SerializationContext)
proc newConstructionContext*(): ConstructionContext = proc newConstructionContext*(): ConstructionContext =
new(result) new(result)
result.refs = initTable[Anchor, tuple[id: TypeID, p: pointer]]() result.refs = initTable[Anchor, tuple[tag: Tag, p: pointer]]()
proc newSerializationContext*(s: AnchorStyle, proc newSerializationContext*(s: AnchorStyle,
putImpl: proc(e: Event) {.raises: [], closure.}): putImpl: proc(e: Event) {.raises: [], closure.}):
@ -1223,14 +1223,18 @@ proc constructChild*[O](s: var YamlStream, c: ConstructionContext,
discard s.next() discard s.next()
return return
elif e.kind == yamlAlias: elif e.kind == yamlAlias:
result = cast[ref O](c.refs.getOrDefault(e.aliasTarget).p) let val = c.refs.getOrDefault(e.aliasTarget)
if val.tag != yamlTag(O):
raise constructionError(s, e.startPos,
"alias node refers to object of incompatible type")
result = cast[ref O](val.p)
discard s.next() discard s.next()
return return
new(result) new(result)
template removeAnchor(anchor: var Anchor) {.dirty.} = template removeAnchor(anchor: var Anchor) {.dirty.} =
if anchor != yAnchorNone: if anchor != yAnchorNone:
yAssert(not c.refs.hasKey(anchor)) yAssert(not c.refs.hasKey(anchor))
c.refs[anchor] = (0, cast[pointer](result)) c.refs[anchor] = (yamlTag(O), cast[pointer](result))
anchor = yAnchorNone anchor = yAnchorNone
case e.kind case e.kind