taintable/utils/attrFinder.js
// get a specifcy property referrenced in the file
get a specifcy property referrenced in the file
get a specifcy property referrenced in the file
function read_property(node, path, offset, cmd){
    if (node.hasOwnProperty('property')) {
        if (node.property.type === "Literal"){
            path.splice(offset, 0, node.property.value);
        }else if (node.property.type === "Identifier" && !node.computed){
            path.splice(offset, 0, node.property.name);
        }else if (node.property.type === "MemberExpression"){
            read_property(node.property, path, offset, cmd);
            return; 
        }else if (node.property.type != "Literal" && node.computed){
            while (path.length > offset) path.pop();
        }else {
            console.log(tynt.Red("[x] read_property error: unknown attribute indexing type " + JSON.stringify(node.property.type)));
            console.log(cmd.loc);
            return;
        }
        if ( node.object.type === "Identifier" ){
            path.splice(offset, 0, node.object.name);
            var path_to_store = path.join('.');
            if (cmd.res.indexOf(path_to_store) === -1 ){
                cmd.res.push(path_to_store);
            }
        } else if (node.object.type === "MemberExpression"){
            read_property(node.object, path, offset, cmd);
        } else if (node.object.type === "ThisExpression" ){
            path.splice(offset, 0, "this");
            var path_to_store = path.join('.');
            if (cmd.res.indexOf(path_to_store) === -1 ){
                cmd.res.push(path_to_store);
            }
        } else {
            if ( node.object.type === "CallExpression" ) {
                if (node.object.callee.type === "MemberExpression"){
                    read_property(node.object.callee, path.splice(0,offset), offset, cmd);
                }
                return;
            }
            if ( node.object.type === "Literal" ) return;
            if (node.object.type === "NewExpression") {
                const args = node.object.arguments;
                for (const id in args) read_property(args[id], path.splice(0,offset), offset, cmd);
                return;           
            }
            if (node.object.type === "ConditionalExpression"){
                const args = node.object;
                for (const id in args) read_property(args[id], path.splice(0,offset), offset, cmd);
                return;
            }
            if (node.object.type === "LogicalExpression"){
                var args = node.object;
                while (args.left.type === "LogicalExpression") {
                    read_property(args.right, path.splice(0,offset), offset, cmd);
                    args = args.left;
                }
                read_property(args.right, path.splice(0,offset), offset, cmd);
                read_property(args.left, path.splice(0,offset), offset, cmd);
                return;
            }
            if (node.object.type === "BinaryExpression"){
                var args = node.object;
                while (args.left.type === "BinaryExpression") {
                    read_property(args.right, path.splice(0,offset), offset, cmd);
                    args = args.left;
                }
                read_property(args.right, path.splice(0,offset), offset, cmd);
                read_property(args.left, path.splice(0,offset), offset, cmd);
                return;
            }
            if (node.object.type === "ArrayExpression"){
                const args = node.object.elements; 
                for (const id in args) read_property(args[id], path.splice(0,offset), offset, cmd);
                return;
            }
            console.log("[x] read_property error: unknown object tpye " + JSON.stringify(node.object));
            console.log(cmd.loc);
            return;
        }
    } else{
        path.splice(offset, 0, node.name);
        var path_to_store = path.join('.');
        if (cmd.res.indexOf(path_to_store) === -1 ){
            cmd.res.push(path_to_store);
        }
    }
}
function read_property ( node , path , offset , cmd ) { if ( node . hasOwnProperty ( 'property' ) ) { if ( node . property . type === "Literal" ) { path . splice ( offset , 0 , node . property . value ) ; } else if ( node . property . type === "Identifier" && ! node . computed ) { path . splice ( offset , 0 , node . property . name ) ; } else if ( node . property . type === "MemberExpression" ) { read_property ( node . property , path , offset , cmd ) ; return ; } else if ( node . property . type != "Literal" && node . computed ) { while ( path . length > offset ) path . pop ( ) ; } else { console . log ( tynt . Red ( "[x] read_property error: unknown attribute indexing type " + JSON . stringify ( node . property . type ) ) ) ; console . log ( cmd . loc ) ; return ; } if ( node . object . type === "Identifier" ) { path . splice ( offset , 0 , node . object . name ) ; var path_to_store = path . join ( '.' ) ; if ( cmd . res . indexOf ( path_to_store ) === - 1 ) { cmd . res . push ( path_to_store ) ; } } else if ( node . object . type === "MemberExpression" ) { read_property ( node . object , path , offset , cmd ) ; } else if ( node . object . type === "ThisExpression" ) { path . splice ( offset , 0 , "this" ) ; var path_to_store = path . join ( '.' ) ; if ( cmd . res . indexOf ( path_to_store ) === - 1 ) { cmd . res . push ( path_to_store ) ; } } else { if ( node . object . type === "CallExpression" ) { if ( node . object . callee . type === "MemberExpression" ) { read_property ( node . object . callee , path . splice ( 0 , offset ) , offset , cmd ) ; } return ; } if ( node . object . type === "Literal" ) return ; if ( node . object . type === "NewExpression" ) { const args = node . object . arguments ; for ( const id in args ) read_property ( args [ id ] , path . splice ( 0 , offset ) , offset , cmd ) ; return ; } if ( node . object . type === "ConditionalExpression" ) { const args = node . object ; for ( const id in args ) read_property ( args [ id ] , path . splice ( 0 , offset ) , offset , cmd ) ; return ; } if ( node . object . type === "LogicalExpression" ) { var args = node . object ; while ( args . left . type === "LogicalExpression" ) { read_property ( args . right , path . splice ( 0 , offset ) , offset , cmd ) ; args = args . left ; } read_property ( args . right , path . splice ( 0 , offset ) , offset , cmd ) ; read_property ( args . left , path . splice ( 0 , offset ) , offset , cmd ) ; return ; } if ( node . object . type === "BinaryExpression" ) { var args = node . object ; while ( args . left . type === "BinaryExpression" ) { read_property ( args . right , path . splice ( 0 , offset ) , offset , cmd ) ; args = args . left ; } read_property ( args . right , path . splice ( 0 , offset ) , offset , cmd ) ; read_property ( args . left , path . splice ( 0 , offset ) , offset , cmd ) ; return ; } if ( node . object . type === "ArrayExpression" ) { const args = node . object . elements ; for ( const id in args ) read_property ( args [ id ] , path . splice ( 0 , offset ) , offset , cmd ) ; return ; } console . log ( "[x] read_property error: unknown object tpye " + JSON . stringify ( node . object ) ) ; console . log ( cmd . loc ) ; return ; } } else { path . splice ( offset , 0 , node . name ) ; var path_to_store = path . join ( '.' ) ; if ( cmd . res . indexOf ( path_to_store ) === - 1 ) { cmd . res . push ( path_to_store ) ; } } }
get a specifcy property referrenced in the file
get a specifcy property referrenced in the file
// it is a member expr //[1] handle object property first // it is a array indexing expr (a['c']) // it is a attribute indexing expr (a.c) // it is a nested indexing expr (a[b[c]]),we just igore "a" and read b[c] // for query[key], we only record "query" // so we pop anything after key //[2] handle object base then // this is the end // the object attr is still a nested member expr  // the object attr is 'this' keyword  // now we start to handle special cases // this is statement like func('aaa').b. we only parse func("aaa"); // this is statement like "i love".concat("lynx"), just ignore // this is statement like new String(aaa),we want to get aaa  // this is statement like (a?b:c).aaa, we want a, b, c // this is statement like (a||b).aaa, we want a, b // read right  // read left  // this is statement like (a + b + c).aaa, we want a, b, c // read right  // read left  // this is statement like [a,b].concat(), we want a,b // it is a standalone variable