/** * Constant propogation for common expressions. */ module php/strategy/const-prop/analysis/common/expressions strategies /** * Print-construct */ expression-const-prop(main,get,set,valid-get,valid-put,valid-remove|) = Print(main) ; add-php-simple-value(|PHPInteger(0)) strategies /** * Exit, should actually terminate the program and stop the analysis. * TODO */ expression-const-prop(main,get,set,valid-get,valid-put,valid-remove|) = Exit(main) <+ Die(main) strategies /** * Echo, does not have a value-type */ expression-const-prop(main,get,set,valid-get,valid-put,valid-remove|) = Echo(map(main)) strategies /** * Eval, either value of a 'return' in the code or False. * TODO */ expression-const-prop(main,get,set,valid-get,valid-put,valid-remove|) = Eval(main) strategies // tmp-strategy, will be expanded with real functioncalls expression-const-prop(main,get,set,valid-get,valid-put,valid-remove|) = FunctionCall(id,map(main)) /***********************************************************************\ Start Array Handling \***********************************************************************/ strategies /** * Creation of an array */ expression-const-prop(main,get,set,valid-get,valid-put,valid-remove|) = ?term@Array(_) ; where( aid := <get-new-php-array-id>) ; Array(map(try(main ; add-array-pairs-to-array(main,get,valid-put,valid-remove|aid)))) ; add-php-simple-value(|aid) ; try( where(tmpval := <get> term) ; set(|tmpval) ) /** * Adds a array pair to a given ArrayObject. * If the value cannot be retrieved the strategy will update * the highest index and fail. * * @type (None(),value) -> Value */ add-array-pairs-to-array(main,get,valid-put,valid-remove|aid) = ?Pair(None(),Value(value)) ; where( ( value' := <get-php-simple-value> value ; key := <add-array-entry(|value')> aid ; try( <add-array-entry(valid-put|key,<get> value)> aid )) <+ <add-array-entry(valid-put|<get> value)> aid <+ (<increase-highest-array-index(|1)> aid ; fail ) ) /** * @type (None(),RefValue) -> Value */ add-array-pairs-to-array(main,get,valid-put,valid-remove|aid) = ?Pair(None(),RefValue(<main ; ?cvar>)) ; where( if (value-identifier,_) := <extract-php-value-identifier-kind(main,valid-remove|) ; (get-php-value-identifier-pair <+ get-php-value-identifier-pair(get) )> cvar then <add-array-entry-reference(|value-identifier)> aid else <increase-highest-array-index(|1)> aid ; fail end ) /** * Adds a array pair to a given Array. * Returns the value that is inserted * * @type (Some(Key(key)),value) -> value */ add-array-pairs-to-array(main,get,valid-put,valid-remove|aid) = ?Pair(Some(Key(<main ; ?key>)),Value(value)) ; where( finalkey := <map-type-to-php-array-key(main,valid-remove|aid)> key ;(( value' := <get-php-simple-value> value ; <add-array-entry(|finalkey,value')> aid ; try( <add-array-entry(valid-put|finalkey,<get> value)> aid ) ) <+ (try( <add-array-entry(valid-put|finalkey,<get> value)> aid <+ <remove-array-entry(valid-remove|finalkey)> aid ) ; <remove-array-entry(|finalkey)> aid // assignment with unknown value ) ) ) /** * @type (Some(Key(key)),RefValue) -> value */ add-array-pairs-to-array(main,get,valid-put,valid-remove|aid) = ?Pair(Some(Key(<main ; ?key>)),RefValue(<main ; ?cvar>)) ; where( finalkey := <map-type-to-php-array-key(main,valid-remove|aid)> key ; if (value-identifier,_) := <extract-php-value-identifier-kind(main,valid-remove|) ; (get-php-value-identifier-pair <+ get-php-value-identifier-pair(get)) > cvar then <add-array-entry-reference(|finalkey,value-identifier)> aid else <remove-array-entry(|finalkey)> aid // assignment to an unknown entry ; try( <remove-array-entry(valid-remove|finalkey)> aid ) ; fail // should fail, otherwise the expression will have a value end ) extract-php-value-identifier-kind(main,valid-remove|) = ( ?Variable(kind) <+ ( ( ?ArrayAccess(<main ; ?var>,Some(<main ; ?key>)) <+ ?StringAccess(<main ; ?var>,<main ; ?key>) ) ; aid := <get-simple-array-value> var ; finalkey := <map-type-to-php-array-key(main,valid-remove|aid)> key ; kind := (aid,finalkey) ) ); !kind /** * Extracts the type of an expression and maps this to * an array-key. * * @type Expr -> arraykey */ map-type-to-php-array-key(main,valid-remove|aid) = ?key ; if key' := <main ; get-simple-raw-value> key then ( (<?True() > key' ; finalkey := 1) <+ (<?False()> key' ; finalkey := 0) <+ (<?PHPArray(_)> key' ; fail) // array's can not be keys <+ (<is-string> key' ; finalkey := key') <+ (<is-int> key' ; finalkey := key') <+ (<is-real> key' ; finalkey := <int> key' ) <+ (<?PHPNull()> key' ; finalkey := "" ) ) else <remove-all-array-entries> aid ; try( <remove-all-array-entries(valid-remove)> aid ) end /***********************************************************************\ End Array Handling \***********************************************************************/ /***********************************************************************\ Start List Handling \***********************************************************************/ strategies expression-const-prop(main,get,set,valid-get,valid-put,valid-remove|) = ListAssign(id ,main) ; ?ListAssign(List(vars),array) ; where( <has-php-array-value> array ; aid := <get-simple-array-value> array ; <eval-php-list-expression(valid-get,valid-put|)> (List(vars),aid) ) ; add-php-simple-value(|aid) ; try( where(tmpval := <get> array) ; set(|tmpval) ) /** * Evaluates a tuple of a List(vars) and a given * Array Id. The values of the array are retrieved and assigned * to the values in vars, if any. * * @type (List(vars),aid) -> ([],[]) */ eval-php-list-expression(valid-get,valid-put|) = ?(List(vars),aid) ; values := <get-array-values> aid ; <ZipAndAssignLists> (vars, values) ; try( values' := <get-array-values(valid-get)> aid ; <ZipAndAssignLists(valid-get,valid-put|)> (vars, values) ) /***********************************************************************\ End List Handling \***********************************************************************/ /***********************************************************************\ Start Inclusion Handling \***********************************************************************/ strategies /** * Evaluates an inclusion of an file if the expression given to the * include-function can be evaluated. */ inclusion-const-prop(main,get,set,rule-union|)= ( Include(main) <+ Require(main) ) ;( ?term@Include(expr) <+ ?term@Require(expr) ) ; where( (value,requireid) := <php-generic-always-include(main|)> expr) ; try( add-inclusion-id(|requireid) ; add-php-simple-value(|value) ) ;try( where (val := <get> term) ; set(|val) ) inclusion-const-prop(main,get,set,rule-union|) = ( IncludeOnce(main) <+ RequireOnce(main) ) ;( ?term@IncludeOnce(expr) <+ ?term@RequireOnce(expr) ) ; where( (value,requireid) := <php-generic-once-include(main,rule-union|)> expr) ; try( add-inclusion-id(|requireid) ; add-php-simple-value(|value) ) ;try( where (val := <get> term) ; set(|val) ) /** * Evaluates a "no-inclusion". This an inclusion that is not possible. * It will remove _all_ dynamic rules that are involved in this evaluation. * * @type include-term -> include-term */ no-inclusion-const-prop(main|name) = ( RequireOnce(main) <+ Include(main) <+ Require(main) <+ IncludeOnce(main) ); where( php-remove-all-eval-dynamic-rules ; try(php-remove-all-eval-dynamic-rules(|name)) ) strategies /** * Always includes a file with a given filename * * @type Expr -> (Expr(evaluated),value) */ php-generic-always-include(main|) = ?expr; filename := <get-simple-raw-string-value> expr ; inclusionId := <process-inclusion(php-generic-include-strategy(main|))> filename ; !(PHPInteger(1),inclusionId) //for now we always return one if suceeded. Should check for an return /** * Includes a file with a given filename if it is * not already in the environment * * @type Expr -> (Expr(evaluated),value,InclusionId) */ php-generic-once-include(main,rule-union|) = ?expr; filename := <get-simple-raw-string-value> expr ; file := <find-php-file> ; <?FILE(filepath)> file ; env := <get-php-environment> ; if <is-file-included(|filepath); ?iid> env then log(|Debug(), "This file was previously included: ", filepath) ; inclusionId := iid else if <is-file-maybe-included(|filepath); ?iid> env then log(|Debug(), "This file could be previously included: ", filepath) ; inclusionId := iid ; {| InclusionMode : rules(InclusionMode: _ -> DefIncluded() ) ; <add-inclusion-filename(|filepath,iid)> env |} ; rule-union(id, <process-inclusion(php-generic-include-strategy(main|))> filename) else inclusionId := <process-inclusion(php-generic-include-strategy(main|))> filename // not yet included end end ; !(PHPInteger(1),inclusionId) //for now we always return one if suceeded. Should check for an return /** * Generic part for the inclusion strategy. This strategy is applied * to every file that is included. Environment is updated and then the * file is evaluated. * * @type AST -> AST */ php-generic-include-strategy(main|) = ?doc ; fill-php-environment(|doc) ; <main> doc /***********************************************************************\ End Inclusion Handling \***********************************************************************/