Changeset b81fd95


Ignore:
Timestamp:
Jul 29, 2020, 11:29:01 PM (14 months ago)
Author:
Michael Brooks <mlbrooks@…>
Branches:
arm-eh, jacob/cs343-translation, master, new-ast, new-ast-unique-expr
Children:
0c760db
Parents:
1d17939
Message:

Fix bug where pointer and reference types allow unsound initialization and return. Fixes #189

There are two instances of the same basic change, which is using conversionCost instead of castCost for resolving...
A: an InitExpr?, always; affects variable initializations
B: a CastExpr?, for type-system-generated casts only; affects function returns

Changing the behaviour of the typechecker on initialization (do A) and cast (do B):
src/ResolvExpr/AlternativeFinder.cc
src/SynTree/Expression.h
testsinit1.*

Making type of string literal consistent with how C defines it (accommodate A):
src/Parser/ExpressionNode.cc

Making type system happy with incumbent use of void* (accommodate A):
libcfa/src/concurrency/kernel.cfa
libcfa/src/containers/list.hfa
tests/bugs/66.cfa
tests/avltree/avl1.cfa
tests/concurrent/signal/block.cfa
tests/searchsort.cfa

Making type system happy with incumbent plan-9 downcast (accommodate B):
libcfa/src/containers/list.hfa

Fixing previously incorrect constness of declarations (accommodate A):
tests/exceptions/defaults.cfa
libcfa/src/iostream.hfa

Fixing previously incorrect isGenerated classification of casts that desugaring introduces (accommodate B):
src/Concurrency/Keywords.cc
src/Concurrency/Waitfor.cc

Working around trac #207 (revealed by A):
tests/io2.cfa

Working around trac #208 (speculatively created by B):
libcfa/src/bits/locks.hfa
libcfa/src/concurrency/preemption.cfa

Misc:
tests/exceptions/conditional.cfa (accommodate A)

a _msg function for an exception was declared with wrong return type, so it was not compatible for assignment into the vtable instance

libcfa/src/stdlib.hfa

the compiler now prohibits a prior attempt to call a nonexistent realloc overload; calling alloc_align in its place

Files:
2 added
18 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/bits/locks.hfa

    r1d17939 rb81fd95  
    130130                pthread_mutex_init(&lock, &mattr);
    131131
    132                 pthread_cond_init (&cond, 0p);
     132                pthread_cond_init (&cond, (const pthread_condattr_t *)0p);  // workaround trac#208: cast should not be required
    133133                val = 0;
    134134        }
  • libcfa/src/concurrency/kernel.cfa

    r1d17939 rb81fd95  
    10751075
    10761076void kernel_abort_msg( void * kernel_data, char * abort_text, int abort_text_size ) {
    1077         $thread * thrd = kernel_data;
     1077        $thread * thrd = ( $thread * ) kernel_data;
    10781078
    10791079        if(thrd) {
  • libcfa/src/concurrency/preemption.cfa

    r1d17939 rb81fd95  
    481481        sigset_t oldset;
    482482        int ret;
    483         ret = pthread_sigmask(0, 0p, &oldset);
     483        ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
    484484        if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
    485485
  • libcfa/src/containers/list.hfa

    r1d17939 rb81fd95  
    2222\
    2323static inline NODE& $tempcv_e2n(ELEM &node) { \
    24         return node; \
     24        return ( NODE & ) node; \
    2525} \
    2626\
     
    187187                $next_link(singleton_to_insert) = $next_link(list_pos);
    188188                if ($next_link(list_pos).is_terminator) {
    189                         dlist(Tnode, Telem) *list = $next_link(list_pos).terminator;
     189                        dlist(Tnode, Telem) *list = ( dlist(Tnode, Telem) * ) $next_link(list_pos).terminator;
    190190                        $dlinks(Telem) *list_links = & list->$links;
    191191                        $mgd_link(Telem) *list_last = & list_links->prev;
     
    210210                $prev_link(singleton_to_insert) = $prev_link(list_pos);
    211211                if ($prev_link(list_pos).is_terminator) {
    212                         dlist(Tnode, Telem) *list = $prev_link(list_pos).terminator;
     212                        dlist(Tnode, Telem) *list = ( dlist(Tnode, Telem) * ) $prev_link(list_pos).terminator;
    213213                        $dlinks(Telem) *list_links = & list->$links;
    214214                        $mgd_link(Telem) *list_first = & list_links->next;
     
    275275
    276276                if ( $prev_link(list_pos).is_terminator ) {
    277                         dlist(Tnode, Telem) * tgt_before = $prev_link(list_pos).terminator;
     277                        dlist(Tnode, Telem) * tgt_before = ( dlist(Tnode, Telem) * ) $prev_link(list_pos).terminator;
    278278                        $dlinks(Telem) * links_before = & tgt_before->$links;
    279279                        &incoming_from_prev = & links_before->next;
     
    285285
    286286                if ( $next_link(list_pos).is_terminator ) {
    287                         dlist(Tnode, Telem) * tgt_after = $next_link(list_pos).terminator;
     287                        dlist(Tnode, Telem) * tgt_after = ( dlist(Tnode, Telem) * ) $next_link(list_pos).terminator;
    288288                        $dlinks(Telem) * links_after = & tgt_after->$links;
    289289                        &incoming_from_next = & links_after->prev;
  • libcfa/src/iostream.hfa

    r1d17939 rb81fd95  
    363363        _Istream_Cstr excl( const char scanset[], char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : true } }; }
    364364        _Istream_Cstr & excl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; }
    365         _Istream_Cstr ignore( const char s[] ) { return (_Istream_Cstr)@{ s, 0p, -1, { .flags.ignore : true } }; }
     365        _Istream_Cstr ignore( char s[] ) { return (_Istream_Cstr)@{ s, 0p, -1, { .flags.ignore : true } }; }
    366366        _Istream_Cstr & ignore( _Istream_Cstr & fmt ) { fmt.flags.ignore = true; return fmt; }
    367367        _Istream_Cstr wdi( unsigned int w, char s[] ) { return (_Istream_Cstr)@{ s, 0p, w, { .all : 0 } }; }
  • libcfa/src/stdlib.hfa

    r1d17939 rb81fd95  
    232232                size_t osize = malloc_size( ptr );                              // current allocation
    233233                size_t nsize = dim * sizeof(T);                                 // new allocation
    234                 T * nptr = realloc( ptr, align, nsize );                // CFA realloc
     234                T * nptr = alloc_align( ptr, align, nsize );    // CFA alloc_align
    235235                if ( nsize > osize ) {                                                  // larger ?
    236236                        memset( (char *)nptr + osize, (int)fill, nsize - osize ); // initialize added storage
     
    243243                size_t nsize = dim * sizeof(T);                                 // new allocation
    244244                size_t ndim = nsize / sizeof(T);                                // new dimension
    245                 T * nptr = realloc( ptr, align, nsize );                // CFA realloc
     245                T * nptr = alloc_align( ptr, align, nsize );            // CFA alloc_align
    246246                if ( ndim > odim ) {                                                    // larger ?
    247247                        for ( i; odim ~ ndim ) {
  • src/Concurrency/Keywords.cc

    r1d17939 rb81fd95  
    510510                                                new CastExpr(
    511511                                                        new VariableExpr( func->get_functionType()->get_parameters().front() ),
    512                                                         func->get_functionType()->get_parameters().front()->get_type()->stripReferences()->clone()
     512                                                        func->get_functionType()->get_parameters().front()->get_type()->stripReferences()->clone(),
     513                                                        false
    513514                                                )
    514515                                        )
     
    888889                        new SingleInit( new UntypedExpr(
    889890                                new NameExpr( "get_monitor" ),
    890                                 {  new CastExpr( new VariableExpr( args.front() ), arg_type ) }
     891                                {  new CastExpr( new VariableExpr( args.front() ), arg_type, false ) }
    891892                        ))
    892893                );
     
    909910                                        {
    910911                                                new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ),
    911                                                 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )
     912                                                new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) )
    912913                                        },
    913914                                        noDesignators,
     
    946947                                        return new SingleInit( new UntypedExpr(
    947948                                                new NameExpr( "get_monitor" ),
    948                                                 {  new CastExpr( new VariableExpr( var ), type ) }
     949                                                {  new CastExpr( new VariableExpr( var ), type, false ) }
    949950                                        ) );
    950951                                })
     
    970971                                                new SingleInit( new VariableExpr( monitors ) ),
    971972                                                new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) ),
    972                                                 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )
     973                                                new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) )
    973974                                        },
    974975                                        noDesignators,
  • src/Concurrency/Waitfor.cc

    r1d17939 rb81fd95  
    384384                                                                decl_monitor
    385385                                                        )
    386                                                 )
     386                                                ),
     387                                                false
    387388                                        );
    388389
     
    408409                        new CompoundStmt({
    409410                                makeAccStatement( acceptables, index, "is_dtor", detectIsDtor( clause.target.function )                                    , indexer ),
    410                                 makeAccStatement( acceptables, index, "func"   , new CastExpr( clause.target.function, fptr_t )                            , indexer ),
     411                                makeAccStatement( acceptables, index, "func"   , new CastExpr( clause.target.function, fptr_t, false )                     , indexer ),
    411412                                makeAccStatement( acceptables, index, "data"   , new VariableExpr( monitors )                                              , indexer ),
    412413                                makeAccStatement( acceptables, index, "size"   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ),
     
    531532                                                                decl_mask
    532533                                                        )
    533                                                 )
     534                                                ),
     535                                                false
    534536                                        ),
    535537                                        timeout
  • src/Parser/ExpressionNode.cc

    r1d17939 rb81fd95  
    427427                if ( str[1] == '8' ) goto Default;                              // utf-8 characters => array of char
    428428                // lookup type of associated typedef
    429                 strtype = new TypeInstType( Type::Qualifiers( Type::Const ), "char16_t", false );
     429                strtype = new TypeInstType( Type::Qualifiers( ), "char16_t", false );
    430430                break;
    431431          case 'U':
    432                 strtype = new TypeInstType( Type::Qualifiers( Type::Const ), "char32_t", false );
     432                strtype = new TypeInstType( Type::Qualifiers( ), "char32_t", false );
    433433                break;
    434434          case 'L':
    435                 strtype = new TypeInstType( Type::Qualifiers( Type::Const ), "wchar_t", false );
     435                strtype = new TypeInstType( Type::Qualifiers( ), "wchar_t", false );
    436436                break;
    437437          Default:                                                                                      // char default string type
    438438          default:
    439                 strtype = new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char );
     439                strtype = new BasicType( Type::Qualifiers( ), BasicType::Char );
    440440        } // switch
    441441        ArrayType * at = new ArrayType( noQualifiers, strtype,
  • src/ResolvExpr/AlternativeFinder.cc

    r1d17939 rb81fd95  
    12161216                        unify( castExpr->result, alt.expr->result, alt.env, needAssertions,
    12171217                                haveAssertions, openVars, indexer );
    1218                         Cost thisCost = castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(),
    1219                                 indexer, alt.env );
     1218                        Cost thisCost =
     1219                                castExpr->isGenerated
     1220                                ? conversionCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(),   indexer, alt.env )
     1221                                : castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(), indexer, alt.env );
    12201222                        PRINT(
    12211223                                std::cerr << "working on cast with result: " << castExpr->result << std::endl;
     
    16981700
    16991701                                // unification run for side-effects
    1700                                 unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
     1702                                bool canUnify = unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
     1703                                (void) canUnify;
    17011704                                // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?
    17021705
    1703                                 Cost thisCost = castCost( alt.expr->result, toType, alt.expr->get_lvalue(),
     1706                                Cost thisCost = computeConversionCost( alt.expr->result, toType, alt.expr->get_lvalue(),
    17041707                                        indexer, newEnv );
     1708
     1709                                PRINT(
     1710                                        Cost legacyCost = castCost( alt.expr->result, toType, alt.expr->get_lvalue(),
     1711                                                indexer, newEnv );
     1712                                        std::cerr << "Considering initialization:";
     1713                                        std::cerr << std::endl << "  FROM: "; alt.expr->result->print(std::cerr);
     1714                                        std::cerr << std::endl << "  TO: ";   toType          ->print(std::cerr);
     1715                                        std::cerr << std::endl << "  Unification " << (canUnify ? "succeeded" : "failed");
     1716                                        std::cerr << std::endl << "  Legacy cost " << legacyCost;
     1717                                        std::cerr << std::endl << "  New cost " << thisCost;
     1718                                        std::cerr << std::endl;
     1719                                )
     1720                               
    17051721                                if ( thisCost != Cost::infinity ) {
    17061722                                        // count one safe conversion for each value that is thrown away
  • src/SynTree/Expression.h

    r1d17939 rb81fd95  
    206206  public:
    207207        Expression * arg;
    208         bool isGenerated = true; // cast generated implicitly by code generation or explicit in program
     208
     209        // Inidicates cast is introduced by the CFA type system.
     210        // true for casts that the resolver introduces to force a return type
     211        // false for casts from user code
     212        // false for casts from desugaring advanced CFA features into simpler CFA
     213        // example
     214        //   int * p;     // declaration
     215        //   (float *) p; // use, with subject cast
     216        // subject cast isGenerated means we are considering an interpretation with a type mismatch
     217        // subject cast not isGenerated means someone in charge wants it that way
     218        bool isGenerated = true;
    209219
    210220        CastExpr( Expression * arg, bool isGenerated = true );
  • tests/avltree/avl1.cfa

    r1d17939 rb81fd95  
    2424tree(K, V) * create(K key, V value) {
    2525  // infinite loop trying to resolve ... t = malloc();
    26   tree(K, V) * t = malloc(sizeof(tree(K,V)));
     26  tree(K, V) * t = ( tree(K, V) * ) malloc(sizeof(tree(K,V)));
    2727  (*t){ key, value };
    2828  return t;
  • tests/bugs/66.cfa

    r1d17939 rb81fd95  
    55
    66int main() {
    7         int * next = (void*)0;
     7        int * next = 0p;
    88        if( next ) {
    99                return 1;
  • tests/concurrent/signal/block.cfa

    r1d17939 rb81fd95  
    8282        if( !is_empty( cond ) ) {
    8383
    84                 $thread * next = front( cond );
     84                $thread * next = ( $thread * ) front( cond );
    8585
    8686                if( ! signal_block( cond ) ) {
  • tests/exceptions/conditional.cfa

    r1d17939 rb81fd95  
    1717};
    1818
    19 void num_error_msg(num_error * this) {
     19const char * num_error_msg(num_error * this) {
    2020    if ( ! this->msg ) {
    2121        static const char * base = "Num Error with code: X";
  • tests/exceptions/defaults.cfa

    r1d17939 rb81fd95  
    1313}
    1414
    15 char * get_log_message(log_message * this) {
     15const char * get_log_message(log_message * this) {
    1616        return this->msg;
    1717}
     
    2828        // We can catch log:
    2929        try {
    30                 throwResume (log_message){(char *)"Should be printed.\n"};
     30                throwResume (log_message){"Should be printed.\n"};
    3131        } catchResume (log_message * this) {
    3232                printf("%s", this->virtual_table->msg(this));
    3333        }
    3434        // But we don't have to:
    35         throwResume (log_message){(char *)"Should not be printed.\n"};
     35        throwResume (log_message){"Should not be printed.\n"};
    3636}
    3737
  • tests/io2.cfa

    r1d17939 rb81fd95  
    121121
    122122        [int, int, const char *, double] t3 = { 3, 4, "a", 7.2 };
    123         sout | [ 3, 4, "a", 7.2 ];
     123        sout | [ 3, 4, (const char*)"a", 7.2 ];             // workaround trac#207: the const cast should not be needed
    124124        sout | t3;
    125125        sepSetTuple( sout, " " );
  • tests/searchsort.cfa

    r1d17939 rb81fd95  
    3838        } // for
    3939        sout | nl;
    40         for ( i; 0 ~ size ) {           // C version
     40        for ( i; 0 ~ size ) {           // C version, returns void*
    4141                int key = size - i;
    42                 int * v = bsearch( &key, iarr, size, sizeof( iarr[0] ), comp );
     42                int * v = ( int * ) bsearch( &key, iarr, size, sizeof( iarr[0] ), comp );
    4343                sout | key | ':' | *v | ", ";
    4444        } // for
Note: See TracChangeset for help on using the changeset viewer.