chapel-lang / chapel

a Productive Parallel Programming Language
https://chapel-lang.org
Other
1.8k stars 423 forks source link

Collection of internal errors found from fuzzing #13097

Closed ronawho closed 4 months ago

ronawho commented 5 years ago

Collection of some of the more interesting bugs I hit while fuzzing. I imagine I'll have more over time, but these are some pretty simple ones to start. These particular ones were found by taking the spec tests and removing a character at a time. I did some minor minification, but they're pretty close to the original tests. Removing the commented out code will allow the tests to compile.

sparse-error.chpl (alist OOB from missing arg to subdomain):

const D = {1..5, 1..5};
var SpsD: sparse subdomain(/*D*/);

// internal error: Indexing list out of bounds [AST/alist.cpp:73]

decl-with-anon-domain.chpl (resolution assert from missing comma in anon array):

var A: [1..2] [1..3] real = [[1.1, 1.2, 1.3]/*,*/ [2.1, 2.2, 2.3]];
writeln(A.domain);

// ChapelBase.chpl:895: internal error: assertion error [functionResolution.cpp:8821]

getDomainMap.chpl (resolution assert from function name typo + generic arg):

use BlockDist;
proc foo(d : domain) where /*i*/sSubtype(d.dist.type, Block) { }
proc foo(d : domain) { }
var D = {1..10} dmapped Block({1..10});
foo(D);

// getDomainMap.chpl:2: internal error: the type of the actual argument 'Block' is generic
bradcray commented 5 years ago

I changed the label to bugs because I consider any instance of "internal error" to indicate a bug in the compiler. Does the fuzzer not have an option to automatically add futures for such cases? :D

jabraham17 commented 4 months ago

These are no longer internal errors and instead give appropriate errors

const D = {1..5, 1..5};
var SpsD: sparse subdomain(/*D*/);

Outputs

foo.chpl:2: syntax error: near ')'
var A: [1..2] [1..3] real = [[1.1, 1.2, 1.3]/*,*/ [2.1, 2.2, 2.3]];
writeln(A.domain);

Outputs

foo.chpl:1: error: Arrays with anonymous domains must either be defined using a list of ranges or use curly brackets.  If you were trying to create an array over a set of 'real(64)' indices, please use curly brackets.
use BlockDist;
proc foo(d : domain) where /*i*/sSubtype(d.dist.type, Block) { }
proc foo(d : domain) { }
var D = {1..10} dmapped Block({1..10});
foo(D);

outputs

foo.chpl:1: In module 'foo':
foo.chpl:4: warning: 'Block' is deprecated, please use 'blockDist' instead
foo.chpl:2: In function 'foo':
foo.chpl:2: warning: 'Block' is deprecated, please use 'blockDist' instead
foo.chpl:1: In module 'foo':
foo.chpl:4: warning: omitting 'new' in a dmapped initialization expression is deprecated; please use '<domain> dmapped new <DistName>(<args>)'
foo.chpl:2: In function 'foo':
foo.chpl:2: warning: need '(?)' on the type 'domain(?)' of the formal 'd' because this type is generic
foo.chpl:3: In function 'foo':
foo.chpl:3: warning: need '(?)' on the type 'domain(?)' of the formal 'd' because this type is generic
foo.chpl:2: In function 'foo':
foo.chpl:2: error: 'domain.dist' is no longer supported, use 'domain.distribution' instead
  foo.chpl:1: called as foo(d: domain(unmanaged BlockDom(1,int(64),one,unmanaged DefaultDist)))
note: generic instantiations are underlined in the above callstack

Resolving some of the deprecations and errors for a new test case also works.

use BlockDist;
proc foo(d : domain) where /*i*/sSubtype(d.distribution.type, blockDist) { }
proc foo(d : domain) { }
var D = {1..10} dmapped new blockDist({1..10});
foo(D);
foo.chpl:2: In function 'foo':
foo.chpl:2: warning: need '(?)' on the type 'domain(?)' of the formal 'd' because this type is generic
foo.chpl:3: In function 'foo':
foo.chpl:3: warning: need '(?)' on the type 'domain(?)' of the formal 'd' because this type is generic
foo.chpl:2: In function 'foo':
foo.chpl:2: error: unresolved call 'sSubtype(type blockDist(1,int(64),unmanaged DefaultDist), type blockDist)'
foo.chpl:2: note: because no functions named sSubtype found in scope
  foo.chpl:1: called as foo(d: BlockDom(1,int(64),one,unmanaged DefaultDist))
note: generic instantiations are underlined in the above callstack

Resolved the warning about (?) still results in the error: unresolved call 'sSubtype'

bradcray commented 4 months ago

Nice! Do you think it's worth adding tests to lock in these behaviors, or do you think they're already well-covered elsewhere / too weird to be worth it?

jabraham17 commented 4 months ago

Nice! Do you think it's worth adding tests to lock in these behaviors, or do you think they're already well-covered elsewhere / too weird to be worth it?

I was on the fence about this and leaned towards not doing it, as they felt too weird to be worth it.

That said, I think it would be great to run some kind of automatic fuzzing nightly that generates tests like this to check for internal errors. But I think that is a bigger lift and probably deserves its own issue

bradcray commented 4 months ago

I buy that argument, just wanted to check. I also agree with the auto-fuzzing concept (which I think was proposed to us verbally at one point, and is very likely what led to this issue being filed (?)), at least eventually. It doesn't necessarily feel like a priority to me today, relative to other things.

ronawho commented 4 months ago

Nice! Yeah, this was partially motivated by https://github.com/chapel-lang/chapel/issues/9987.

Even at the time, I don't think was a high priority and was something I explored for one of my classes. I probably have more notes somewhere, but my memory is that using a real fuzzer like AFL was way too slow and didn't result in interesting programs. So I ended up taking known good programs and making slight modifications to them and looking for internal errors. Even that was really slow, so I ended up writing a chapel program to spread the permutations out across an internal cluster (was way easier to create a block distributed array of filenames and do a spawn for each element or something on each node than to write a distributed tester from scratch.)