carp-lang / carp-lang/Carp

Complex case leads to free before allocation

Open
#997 21 comments 0 reactions 0 assignees View on GitHub
bug haskell memory
Dominant language
Haskell
Stars
6k
Forks
187
Avg merge
8d 22h
Merged PRs (30d)
4

Description

I've run into a case where a String is freed before it's actually used, here's the code:

```clojure
(defn binary-partial [f x]
(fn [y]
(f x y)))
(doc lift-binary
"Lifts a binary function into an applicative structure.")
(defn lift-binary [f cx cy]
(sequence (fmap &(binary-partial binary-partial f) cx) cy))

(deftype (Box a) [of a])

(defmodule Box
(implements fmap fmap)
(defn fmap [f b]
(let [val (~f @(Box.of &b))]
(Box.init val)))

(implements fmap! fmap!)
(defn fmap! [f b]
(let [val (~f @(Box.of b))]
(Box.set-of! b val)))

(implements lift Box.init)

(implements sequence seq)
(defn seq [box-f box]
(let [f @(Box.of &box-f)
v @(Box.of &box)]
(Box.init (f v))))

(implements sequence! seq!)
(defn seq! [box-f box]
(let [f @(Box.of box-f)
v @(Box.of box)]
(Box.set-of! box (f v))))

)
```

Loading up this code and then running:

```clojure
鲤 (defn foo [] (Applicative.lift-binary (fn [x y] (String.append &x &y)) (Box.init @"foo") (Box.init @"bar")))
鲤 (foo)
Compiled to 'out/Untitled' (executable)
Untitled(3776,0x10c0a7dc0) malloc: *** error for object 0x7fc502c05830: pointer being freed was not allocated
Untitled(3776,0x10c0a7dc0) malloc: *** set a breakpoint in malloc_error_break to debug
[RUNTIME ERROR] '"out/Untitled"' exited with return value -6.

```

It emits a free before allocation here:

```c
void FP__Lambda_binary_MINUS_partial__String_String_String_12_env_delete(FP__Lambda_binary_MINUS_partial__String_String_String_12_env* p) {
Function_delete__String_String_String(p->f);
String_delete(p->x);
}
```

commenting out `String_delete(p->x);` makes it run fine:

```
./foo
(Box @"foobar")
```

I thought this might have to do with capturing vars, but it perhaps doesn't since this works fine:

```clojure
鲤 (defn foo [] (Applicative.lift-binary (fn [x y] (+ x y)) (Box.init 1) (Box.init 2)))
鲤 (foo)
Compiled to 'out/Untitled' (executable)
(Box 3)
=> 0
```

Seems specifically related to Strings or `String.append`as well, not references in general:

```clojure
鲤 (defn foo [] (Applicative.lift-binary (fn [x y] (add-ref &x &y)) (Box.init 1) (Box.init 2)))
鲤 (foo)
Compiled to 'out/Untitled' (executable)
(Box 3)
=> 0

```

Contributor guide

Open the contributing guide

Research direction

Reproduce the String case and inspect the emitted FP__Lambda_binary_MINUS_partial__String_String_String_12_env_delete function, especially its String_delete call and the surrounding allocation and capture behavior. Compare it with the integer and add-ref examples. Done means the String example runs without an invalid free and produces (Box @"foobar").

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.