Projects

Ticket #142: 142.patch

File 142.patch, 2.9 KB (added by jamis@…, 4 years ago)

Rough (very rough) patch that fixes the infinite loop caused by this issue

  • vm_insnhelper.c

     
    14701470    static ID idNew = 0, idNew2 = 0, idNew3 = 0; 
    14711471    CFMutableDictionaryRef iv_dict; 
    14721472    VALUE ary, k; 
     1473    int looked_up = 0; 
    14731474   
    14741475    if (idNew == 0) { 
    14751476        idNew = rb_intern("new"); 
     
    15121513                                         (const void **)&k)) { 
    15131514        CFDictionaryRemoveValue(iv_dict, (const void *)idPreviousKlass); 
    15141515        klass = k; 
     1516    } else if(RCLASS_MODULE(klass)) { 
     1517        /* If klass is a module, and it has not previously had the idPreviousKlass 
     1518         * variable set in it, then we're in a module that is itself calling super, 
     1519         * and which was not reached via super. E.g.: 
     1520         * 
     1521         *   module A 
     1522         *      def initialize 
     1523         *        super # <--- RIGHT HERE 
     1524         *      end 
     1525         *   end 
     1526         * 
     1527         *   class B 
     1528         *     include A 
     1529         *   end 
     1530         * 
     1531         *   B.new 
     1532         * 
     1533         * In this case, look at the ancestors of the receiver's class, find which 
     1534         * ancestor we're looking at, and then find the *next* ancestor in the list 
     1535         * as the superclass. If that next ancestor is also a module, duplicate the 
     1536         * behavior above and set idPreviousKlass. (This should be refactored out 
     1537         * to avoid duplication.) 
     1538         */ 
     1539        k = CLASS_OF(recv); 
     1540        ary = rb_funcall(k, rb_intern("ancestors"), 0); 
     1541        int i, count = RARRAY_LEN(ary); 
     1542        for (i = 0; !looked_up && i < count-1; i++) { 
     1543            VALUE ancestor = RARRAY_AT(ary, i); 
     1544 
     1545            if(ancestor == klass) { 
     1546                int j; 
     1547                for (j = i+1; !looked_up && j < count; j++) { 
     1548                    k = RARRAY_AT(ary, j); 
     1549                    if(!RCLASS_MODULE(k)) { 
     1550                        looked_up = 1; 
     1551                    } else { 
     1552                        VALUE saved_imod_super; 
     1553                        NODE *mn; 
     1554                        IMP imp; 
     1555                        SEL sel; 
     1556 
     1557                        saved_imod_super = RCLASS_SUPER(k); 
     1558                        RCLASS_SUPER(k) = 0; 
     1559                        mn = rb_objc_method_node(k, mid, &imp, &sel); 
     1560                        RCLASS_SUPER(k) = saved_imod_super; 
     1561                        if (imp != NULL) { 
     1562                            rb_ivar_set(k, idPreviousKlass, klass); 
     1563                            *mnp = mn; 
     1564                            *impp = imp; 
     1565                            *selp = sel; 
     1566                            return k; 
     1567                        } 
     1568                    } 
     1569                } 
     1570            } 
     1571        } 
    15151572    } 
    15161573 
    1517     k = vm_search_normal_superclass(klass, recv); 
     1574    if(!looked_up) 
     1575        k = vm_search_normal_superclass(klass, recv); 
    15181576    
    15191577    /* because #new is added on every new NSObject subclasses, and if overriden 
    15201578       we should still call our implementation with super */