1. pointer in Thing, var param (drawback: you have to make sure that the 
pointer stays valid):


    
    
    type
      Thing = object
        list: ptr seq[int]
    
    proc initThing(list: var seq[int]): Thing =
      result.list = list.addr
    
    
    Run

  2. ref original


    
    
    var original: ref seq[int]
    new(original)
    original[] = @[1, 2, 3, 4, 5]
    
    type
      Thing = object
        list: ref seq[int]
    
    proc initThing(list: ref seq[int]): Thing =
      result.list = list
    
    
    Run

  3. cast ptr to ref (drawback: this is a lie, easy to get a reuse after free):


    
    
    var original = @[1, 2, 3, 4, 5]
    
    type
      Thing = object
        list: ref seq[int]
    
    proc initThing(list: var seq[int]): Thing =
      result.list = cast[ref seq[int]](list.addr)
    
    
    Run

  4. forget about preserving original:


    
    
    type
      Thing = object
        list: ref seq[int]
    
    proc initThing(list: seq[int]): Thing =
      new(result.list)
      result.list[] = list
    
    var thing = initThing(@[1, 2, 3, 4, 5])
    let original = thing.list
    
    
    Run

Example problem with #3:
    
    
    type
      Thing = object
        list: ref seq[int]
    
    proc initThing(list: var seq[int]): Thing =
      result.list = cast[ref seq[int]](list.addr)
    
    var thing: Thing
    new(thing.list)
    block:
      var original = @[1, 2, 3, 4, 5]
      thing = initThing(original)
      original[0] = 666
    
    echo thing.list.repr  # use after free: ref @[666, 0, 3, 20, 
3467820324424670016]
    
    
    Run

Reply via email to