/** * Constant propogation for variables in PHP. */ module php/strategy/evaluation/variables /***********************************************************************\ Start Variable Handling \***********************************************************************/ strategies /** * Variable-construct */ variable-const-prop(main,set,get,get-valid) = ?Variable(var) ; where ( name := <main ; php-get-raw-variable-name> var ) ; try( add-php-simple-value(|<PHPSuperGlobalValue <+ php-variable-value> name)) ; try( set(|<php-variable-value(get-valid)> name)) /** * ConstantVariable-construct */ variable-const-prop(main,set,get,get-valid) = ?ConstantVariable(name) ; try(add-php-simple-value(|<php-constant-get-value> name)) ; try(set(|<php-constant-get-value(get-valid)> name)) /** * @type IndirectReference(_) -> PHPSimpleValue */ variable-const-prop(main,set,get,get-valid) = ?IndirectReference(expr) ; where( expr' := <main> expr ; varname := <get-simple-raw-string-value> expr' ; evalExpr := <main> Variable(Simple(varname)) ) ; try(add-php-simple-value(|<get-php-simple-value> evalExpr)) ; try(set(|<get> evalExpr)) /***********************************************************************\ End Variable Handling \***********************************************************************/ /***********************************************************************\ Start ArrayAccess Handling \***********************************************************************/ strategies /** * General array acces on an array. * @type ArrayAccess(type:PHPArray,expr) -> value */ variable-const-prop(main,set,get,get-valid) = variable-const-prop(main,set,get,get-valid ,array-access-on-array // this one incorperates const-prop itself ,id ,id ) variable-const-prop(main,set,get,get-valid ,array-value ,string-value ,other-value) = ( ArrayAccess(main; ?array,main) <+ StringAccess(main; ?array,main) ) ;(( where( <has-php-array-value> array) ; array-value(main,get,set,get-valid) ) <+ ( where( <has-php-string-value> array) ; array-access-on-string ; string-value ) <+ ( where( <has-php-boolean-value> array <+ <has-php-integer-value> array <+ <has-php-float-value> array <+ <has-php-null-value> array ) ; array-access-on-other ; other-value )) /** * Special case for the GLOBALS array. This array holds all variables, so * we try to extract the value of that variable first. If this fails then we * try the integer value as a key. */ array-access-on-array(main,get,set,valid-get) = ?ArrayAccess(array,Some(expr)) ; where( aid := <get-simple-array-value> array) ;(( where( <is-globals-array> aid ; strkey := <get-simple-raw-string-value> expr ; <explode-string; ?[<is-alpha> | _ ]> strkey ; evalExpr := <main> Variable(Simple(strkey)) ) ; ( try(add-php-simple-value(|<get-php-simple-value> evalExpr)) ; try(set(|<get> evalExpr)) ) ) <+ ( try(add-php-simple-value(|<generic-arrayaccess-value> (aid,expr))) ; try(set(|<generic-arrayaccess-value(valid-get)> (aid,expr))) )) array-access-on-string = ( ?StringAccess(array,expr) <+ ?ArrayAccess(array,Some(expr)) ) ; where( str := <get-simple-raw-string-value> array ; num := <get-simple-raw-integer-value> expr ; if <gt> (num, < string-length> str) then value := "" else <explode-string>str ; at-index( ?ch | num) ; value := <implode-string> [ch] end ) ; add-php-simple-value(|PHPString(value)) array-access-on-other = ?ArrayAccess(val,_) ;( <has-php-boolean-value> val <+ <has-php-integer-value> val <+ <has-php-float-value> val <+ <has-php-null-value> val ) ; add-php-simple-value(|PHPNull()) /** * Generic array-acces for botht the special case for GLOBALS and the * normal case. */ generic-arrayaccess-value = generic-arrayaccess-value(php-val-id-get-rule) generic-arrayaccess-value(valid-get) = ?(aid,expr) ; where (( strkey := <get-simple-raw-string-value> expr ; value := <get-array-entry(valid-get|strkey)> aid ) <+ ( intkey := <get-simple-raw-integer-value> expr ; value := <get-array-entry(valid-get|intkey)> aid ) ) ; !value /** * Checks wheter or not the ArrayId matches that of the GLOBALS-array * @type PHPArray() -> _ */ is-globals-array= ?PHPArray("superglobal_GLOBALS") /***********************************************************************\ End ArrayAccess Handling \***********************************************************************/ /***********************************************************************\ Begin Rules for Variables \***********************************************************************/ /** * Adds a rule that maps a variable to a value. * * @type (name,value) -> (name,value) */ add-php-variable-rule = add-php-variable-rule(php-val-id-add-rule) add-php-variable-rule(valid-put) = ?(Variable(var),value) ; name := <php-get-raw-variable-name> var ; value-identifier := <get-php-value-identifier> var ; rules(EvalPHPVar : name -> value-identifier) //extra pointer to make implementation ; valid-put(|value-identifier,value) //of references easy /** * Adds a mapping from a variable to a value-identifier. * * @type (name,value) -> (name,value) */ add-php-variable-identifier-rule = ?(Variable(var),value-identifier) ; name := <php-get-raw-variable-name> var ; rules(EvalPHPVar: name -> value-identifier) /** * Get's the real value of an variable. This means applying the strategy * EvalPHPVar twice. First getting the pointer to the value and then getting * the real value. * * @type String -> PHPSimpleValue */ php-variable-value = php-variable-value(php-val-id-get-rule) php-variable-value(s) = EvalPHPVar;s /** * Makes a new identifier that is unique for each variable. * Reuses an old identifier if it exists, otherwise it uses the * name of the variable, which should be unique in the program. * * @type name -> String */ get-php-value-identifier = ( php-get-raw-variable-name ; EvalPHPVar ) <+ // no old for variable ( EvalPHPArray ) <+ // no old for array (php-get-raw-variable-name ) <+ // no name, try array {?(aid,key) ; if <is-int> key then key' := <int-to-string> key else key' := key end ; <?PHPArray(aid')> aid ; <conc-strings> (aid',key') } get-php-value-identifier-pair = get-php-value-identifier-pair(php-val-id-get-rule) get-php-value-identifier-pair(valid-get) = ?var ; identifier := <get-php-value-identifier> var ; value := <valid-get> identifier ; !(identifier,value) /** * Extracts the name of a variable. This strategy handles * all the cases that can contain a variable name. * * @type Simple(_) OR Braced() -> String */ php-get-raw-variable-name = ( ?Braced(Simple(name)) <+ ?Simple(name) <+ ( ?Braced(expr) ; name := <get-simple-raw-string-value> expr ) ) ; <rm-annotations> name /** * Removes the rule that maps a variable to a value. * * @type name -> name */ remove-php-variable-rule = remove-php-variable-rule(php-val-id-remove-rule) remove-php-variable-rule(valid-remove) = ?Variable(var) ; name := <php-get-raw-variable-name> var ; value-identifier := <get-php-value-identifier> var ; valid-remove(|value-identifier) // also remove mapping to value. ; rules(EvalPHPVar :- name) // unknown RHS also invalidates all aliases /** * Adds a dynamic rule for a PHP constant. * * @type (String,PHPValue) -> _ */ add-php-constant-rule = add-php-constant-rule(php-constant-put-value) add-php-constant-rule(put-valid) = ?(name,value) ; value_identifier := <newname> "php_constant_" ; rules(EvalPHPConstant: name -> value_identifier) ; put-valid(|value_identifier,value) php-constant-get-value = php-constant-get-value(EvalPHPValId) php-constant-get-value(get-valid) = EvalPHPConstant ; get-valid php-constant-put-value(|ident,val) = rules(EvalPHPValId: ident -> val) php-val-id-remove-rule(|key) = rules(EvalPHPValId :- key) php-val-id-add-rule(|key,val) = rules(EvalPHPValId : key -> val) php-val-id-get-rule = EvalPHPValId rules /** * Rules that rewrite the value of a superglobal to an * array-type. * * @type: String -> PHPArray(_) */ PHPSuperGlobalValue: "_GET" -> PHPArray("superglobal_GET") PHPSuperGlobalValue: "_POST" -> PHPArray("superglobal_POST") PHPSuperGlobalValue: "_REQUEST" -> PHPArray("superglobal_REQUEST") PHPSuperGlobalValue: "_SERVER" -> PHPArray("superglobal_SERVER") PHPSuperGlobalValue: "_FILES" -> PHPArray("superglobal_FILES") PHPSuperGlobalValue: "_ENV" -> PHPArray("superglobal_ENV") PHPSuperGlobalValue: "_COOKIE" -> PHPArray("superglobal_COOKIE") PHPSuperGlobalValue: "GLOBALS" -> PHPArray("superglobal_GLOBALS") PHPSuperGlobalValue: "_SESSION" -> PHPArray("superglobal_SESSION") /***********************************************************************\ End Rules for Variables \***********************************************************************/