[xsmith-dev] XSmith questions

William G Hatch william at hatch.uno
Tue Jun 22 15:08:50 MDT 2021


Oops, I hit `reply` instead of `reply-all`.  I'm adding the mailing
list back on now.

On Tue, Jun 22, 2021 at 03:06:05PM -0600, William G Hatch wrote:
>On Tue, Jun 22, 2021 at 12:43:50PM -0700, Sorawee Porncharoenwase wrote:
>>Hi everyone,
>>
>>I just started using XSmith. I don’t think I grok the framework yet, so I
>>would really appreciate it if anyone could help me!
>
>I'll do my best.  (I'm the main author of Xsmith, so you can blame
>most of your issues on me.)  Xsmith is research software with lots of
>sharp edges and insufficient documentation about those edges, and has
>been successfully used mostly by its authors so far.  (Though at least
>one other person has found some bugs using the fuzzers we've made.)
>
>[This email is a bit rambly and repetetive, sorry.  I would edit it
>better but I need to do something else now.  If this doesn't answer
>your questions, please ask some more follow-up questions and I'll try
>to write more cohesively.]
>
>>1) While I understand that dynamically typed language should specify
>>type-info to generate programs that don’t cause runtime type mismatch, I
>>find it weird that types are very integral to the framework. For example,
>>binder-info seems to presuppose that declaration AST nodes will have type
>>information in it.
>>
>>On one hand, that’s strictly speaking not the case for many languages.
>>
>>On the other hand, I can understand that the specified grammar here doesn’t
>>need to correspond to the actual language grammar. So let’s just add the
>>type field into the AST node. But this raises another question: how do I
>>know which other AST nodes will require additional type information as well?
>
>If you really want to have a language where anything goes, you can
>just create a `dyn` base-type and use it everywhere.  But, as you
>mention, fuzzing will likely be ineffective since things will mostly
>just crash with runtime type errors.  If you want to encode the fact
>that various types can be implicitly coerced, you can add explicit
>conversion AST nodes for Xsmith that go away when you pretty-print the
>program.  Eg. you can define an IntToStringCoersion expression that is
>rendered by just rendering the integer inside without adding anything
>else to it.
>
>Every node in the AST has type information.
>
>Generally, an Xsmith language fuzzer will have 2-3 main AST node
>types: Expression, Statement, and Definition.  Definitions are
>separate to simplify Xsmith itself to do something consistent --
>definitions can be expressions, statements, or something separate in
>various languages, but always having Definition nodes in Xsmith makes
>generic name analysis easier.
>
>Expressions have the types you expect -- string, int, list-of-string,
>etc.
>
>Statement types are a bit of a hack.  Statements have two types:
>no-return-statement and return-statement, which is a wrapper type that
>includes an expression type inside that corresponds to the return type
>of the function.
>
>Definition nodes should have expression types, IE the type of the
>right-hand-side of the definition.
>
>In practice, you probably want to use canned-components to get
>Definition node definitions and probably Statement node definitions as
>well.  If you do that you don't need to provide type information for
>them.  The main place you need to worry about types is with
>expressions.
>
>As an aside, Function definitions are often a special case in
>programming languages, but we basically encode them as a definition
>with a lambda on the right hand side that we maybe print differently.
>(If you want to have both definitions with a lambda on the RHS and
>function definitions with your language's shorthand syntax, you can
>define a new Definition node subtype that prints differently.)
>
>
>>2) As far as I can see, all declaration nodes have types to be that of the
>>expression it contains. Again, I find this weird since declaration in most
>>languages is a statement, not an expression. I tried fixing this by
>>modifying the “Another Small Example with Variables” example to:
>>
>>(add-property
>>arith
>>type-info
>>[Definition [no-return-type (λ (n t) (hash 'Expression
>>(fresh-type-variable)))]]
>>[LetStar [(fresh-type-variable)
>>          (λ (n t) (hash 'definitions (λ (cn) no-return-type)
>>                         'sideEs (λ (cn) (fresh-type-variable))
>>                         'Expression t))]]
>>...)
>>
>>where no-return-type is from xsmith/canned-components. The generation
>>errors with with:
>>
>>Exception:
>>unify!: subtype-unify!: can't unify these types: #<type-variable
>>(#<range:#<no-return-type>-#<no-return-type>>)> and #<int>
>
>You need the type of the definition to be the type of the expression
>of the RHS of the definition (modulo subtyping).  Despite the fact
>that when printing you may make the definitions look like statements,
>Xsmith just requires Definition nodes to have the same type as
>variable references to that definition, and keeps Definition and
>Statement nodes separate.
>
>The return-type/no-return-type is sort of a hack to use the type
>system to keep track of statements as well as expressions.  In eg. a
>function, you need to track the return type throughout the function to
>be sure that the function does return (potentially in multiple
>branches of a conditional), and that all return statements return the
>right type.  So by annotating which nodes do or don't return
>something, Xsmith can be sure to generate well-formed functions.
>
>The key to using Definitions in a statement language is basically a
>`Block`-like statement that can have a series of statements that
>include definitions needs to have a list of definitions and a list of
>statements separately.  This is a bit of a limitation, since many
>languages can interleave definitions and statements, and Xsmith
>basically can't.  At any rate, the `Block` node from canned-components
>does this.
>
>Probably the best way to see how to do it in a full-sized (but still
>relatively simple) example is to look at the simple/javascript.rkt
>file in the xsmith-examples directory.  (We haven't actually used that
>one yet, so I'm not 100% certain it generates actually correct
>javascript, but it should be close if it's wrong.  At any rate, it's
>probably the simplest full-size example to see the correlation between
>the definition of the fuzzer and its output.)
>
>The `Block` statement in canned-components, and that the javascript
>example uses, is the main place to put definitions in a
>statement-based language.  In the javascript example we have a series
>of top-level definitions by using `ProgramWithBlock`, then basically
>unwrapping the “block” and printing the definitions in the top level.
>It also uses `LambdaWithBlock` for function definitions.  So if you
>look at how it's used it should clarify how to have definitions in a
>statement language.
>
>>In most examples that I saw, declarations are hoisted at the very top of
>>function / block / program. I think the no-return-type is particularly
>>going to be a problem when I want to allow declarations and statements to
>>interleave, since statements will be assigned a unique type (like
>>no-return-type), while declarations can’t do the same.
>>
>>3) How do I debug when XSmith simply hangs and doesn’t output anything? It
>>looks like the problems I encountered are with types, since if I relax the
>>constraints, it can generate programs without any problem (though the
>>generated programs are incorrect, as expected).
>
>Xsmith is probably hanging because it is in a lift loop.  IE it has
>created a Definition node, and it needs to generate a right-hand-side
>for the definition.  When it tries to generate the RHS expression, the
>only legal expression it can find is VariableReference.  So it creates
>a VariableReference, and it can't find a (non-circular) variable of
>that type to reference, so it lifts one.  Then it needs to make an RHS
>for that definition as well, and ...
>
>We really ought to catch this situation somehow, crash, and report an
>error.  But we don't at the moment.  Sorry.  If you hit control-C and
>get the debug output, you can see the type of the lift cycle (by just
>seeing what is being lifted over and over), and then try to figure out
>why nothing else is legal.  You may have forgotten a literal node, or
>maybe the literal node has holes (eg. a lambda is a literal but not
>atomic, it needs statements/expressions inside), meaning that you need
>to add an annotation of `#:prop wont-over-deepen #t` so it will
>generate it even if it's at the max AST depth.
>
>>4) In xsmith/canned-components, there are several predefined types, but the
>>module only exports constructors, not accessors. What would be the best way
>>to extract information from it? unify!?
>
>Yes, use `unify!`. Eg.
>
>```
>(define my-return-type (fresh-type-variable))
>(define f (function-type (fresh-type-variable) my-return-type))
>(unify! f some-function-type)
>```
>
>This is something I should also improve but haven't yet.  The basic
>accessors can fail when logically they should succeed because they may
>be passed a type variable instead of the struct for the type you think
>it is.  So if you try to use eg. `(function-type t)` it might fail.  I
>should provide a `function-type!` function that does the obvious
>struct creation and unification, but I haven't yet.
>
>I may add that over the coming weeks.  I've been busy with some other
>things, but am shifting my gears back to Xsmith development, and hope
>to finish a few final features (eg. work on stuff to do
>feedback-directed fuzzing) and do some serious fuzzing with it.
>(We've run fuzz campaigns and found some bugs in the past, but mostly
>switched back to add-more-features mode to try to make it more
>effective, and haven't quite gotten back to actually trying to find
>bugs.)
>
>>Thanks!
>>Sorawee
>
>I hope you find Xsmith useful!  What are you intending to fuzz?  I'm
>also happy to look at any code you have on Github or such for some
>debugging help.



More information about the xsmith-dev mailing list