How to get opcodes of PHP? - php

<?php
$show_value = 123;
echo 'sing_quote'.$show_value;
echo "double_quote{$show_value}";
?>
Its opcode is:
1: <?php
2: $show_value = 123;
0 ASSIGN !0, 123
3: echo 'sing_quote'.$show_value;
1 CONCAT 'sing_quote', !0 =>RES[~1]
2 ECHO ~1
4: echo "double_quote{$show_value}";
3 ADD_STRING 'double_quote' =>RES[~2]
4 ADD_VAR ~2, !0 =>RES[~2]
5 ECHO ~2
6 RETURN 1

Check out the Vulcan Logic Disassembler PECL extension - see author's home page for more info.
The Vulcan Logic Disassembler hooks
into the Zend Engine and dumps all the
opcodes (execution units) of a script.
It was written as as a beginning of an
encoder, but I never got the time for
that. It can be used to see what is
going on in the Zend Engine.
Once installed, you can use it like this:
php -d vld.active=1 -d vld.execute=0 -f yourscript.php
See also this interesting blog post on opcode extraction, and the PHP manual page listing the available opcodes.

Parsekit has parsekit_compile_string().
sudo pecl install parsekit
var_dump(parsekit_compile_string(<<<PHP
\$show_value = 123;
echo 'sing_quote'.\$show_value;
echo "double_quote{\$show_value}";
PHP
));
The output is quite verbose, so you'd need to process it to get assembler-like format.
["opcodes"]=>
array(10) {
[0]=>
array(9) {
["address"]=>
int(44682716)
["opcode"]=>
int(101)
["opcode_name"]=>
string(13) "ZEND_EXT_STMT"
["flags"]=>
int(4294967295)
["result"]=>
array(8) {
["type"]=>
int(8)
["type_name"]=>
string(9) "IS_UNUSED"
["var"]=>
int(0)
["opline_num"]=>
string(1) "0"
["op_array"]=>
string(1) "0"
["jmp_addr"]=>
string(1) "0"
["jmp_offset"]=>
string(8) "35419039"
["EA.type"]=>
int(0)
}
["op1"]=>
array(8) {
["type"]=>
int(8)
["type_name"]=>
string(9) "IS_UNUSED"
["var"]=>
int(0)
["opline_num"]=>
string(1) "0"
["op_array"]=>
string(1) "0"
["jmp_addr"]=>
string(1) "0"
["jmp_offset"]=>
string(8) "35419039"
["EA.type"]=>
int(0)
}

You can run code and also see the opcodes if you use https://3v4l.org/
Note: It automatically shows the Vulcan Logic Disassembler (VLD) output, but only if you have "all supported versions" selected in the version dropdown.
Here's a simple example (shown below for posterity): https://3v4l.org/Gt8fd/vld
Code:
<?php
$arr = [1, 2, 3, 4];
print_r(array_map(fn(int $i): int => $i * $i, $arr));
Result:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename: /in/Gt8fd
function name: (null)
number of ops: 10
compiled vars: !0 = $arr
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
2 0 E > ASSIGN !0, <array>
3 1 INIT_FCALL 'print_r'
2 INIT_FCALL 'array_map'
3 DECLARE_LAMBDA_FUNCTION '%00%7Bclosure%7D%2Fin%2FGt8fd%3A3%240'
4 SEND_VAL ~2
5 SEND_VAR !0
6 DO_ICALL $3
7 SEND_VAR $3
8 DO_ICALL
9 > RETURN 1
Function %00%7Bclosure%7D%2Fin%2FGt8fd%3A3%240:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename: /in/Gt8fd
function name: {closure}
number of ops: 6
compiled vars: !0 = $i
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
0 E > RECV !0
1 MUL ~1 !0, !0
2 VERIFY_RETURN_TYPE ~1
3 > RETURN ~1
4* VERIFY_RETURN_TYPE
5* > RETURN null
End of function %00%7Bclosure%7D%2Fin%2FGt8fd%3A3%240
Generated using Vulcan Logic Dumper, using php 8.0.0

Two options are, setting opcache.opt_debug_level INI setting or using phpdbg binary provided in a debug-enabled PHP environment (e.g. requiring you to either compile PHP from source or install the related package on Linux).
For more information and a full guide, refer to this php.watch article (also credits to this article).

Related

PHP: Custom parser for non-formatted text

I am trying to create a project which will help students study various areas. The idea is that I have a piece of raw text, which contains quiz questions and answers which I want to parse as question header and answer options, which will be inserted into a database. However, the text is not properly formatted and due to the large amount of questions and answers (around ~20k per total), I cannot afford the time to manually insert them or format the text myself.
The raw text looks like this:
1. A car averages 27 miles per gallon. If gas costs $4.04 per gallon, which of the following is closest to how much the gas would cost for this car to travel 2,727 typical miles?
a) $44.44 b) $109.08 c) $118.80
d) $408.04 e)
$444.40
2. When x = 3 and y = 5, by how much does the value of 3x2 – 2y exceed the value of 2x2 – 3y ?
a) 4
b) 14
c) 16
d) 20 e) 50
I tried creating my own PHP functions to parse the text properly, however I cannot get myself to get past the random line breaks, spaces, etc.
What I am trying to obtain:
array(1) {
[0]=>
array(3) {
["questionNumber"]=>
string(1) "1"
["questionText"]=>
string(175) "A car averages 27 miles per gallon. If gas costs $4.04 per gallon, which of the following is closest to how much the gas would cost for this car to travel 2,727 typical miles?"
["options"]=>
array(5) {
["a"]=>
string(6) "$44.44"
["b"]=>
string(7) "$109.08"
["c"]=>
string(7) "$118.80"
["d"]=>
string(7) "$408.04"
["e"]=>
string(7) "$444.40"
}
}
}
The code I have so far:
$rawText = '1. A car averages 27 miles per gallon. If gas costs $4.04 per gallon, which of the following is closest to how much the gas would cost for this car to travel 2,727 typical miles?
a) $44.44 b) $109.08 c) $118.80
d) $408.04 e)
$444.40
2. When x = 3 and y = 5, by how much does the value of 3x2 – 2y exceed the value of 2x2 – 3y ?
a) 4
b) 14
c) 16
d) 20 e) 50
';
$rawTextLines = explode("\n", $rawText);
foreach ($rawTextLines as $lineNumber => $lineContents) {
$lContents = trim($lineContents);
if (empty ($lContents)) {
unset ($rawTextLines[$lineNumber]);
} else {
$rawTextLines[$lineNumber] = $lContents;
}
}
$processedQuestions = array ();
$currentQuestionHeader = 0;
foreach ($rawTextLines as $lineNumber => $lineContents) {
if (ctype_digit(substr($lineContents, 0, 1))) { // Question header
$questionHeaderInformation = explode('.', $lineContents);
$currentQuestionHeader = $questionHeaderInformation[0];
$processedQuestions[$currentQuestionHeader]['questionNumber'] = $currentQuestionHeader;
$processedQuestions[$currentQuestionHeader]['questionText'] = $questionHeaderInformation[1];
} else { // Question option
$options = explode(')', $lineContents);
if (count ($options) % 2 === 0) {
$processedQuestions[$currentQuestionHeader]['options'][trim($options[0])] = ucfirst(trim($options[1]));
} else {
}
}
}
Which produces this:
array(2) {
[1]=>
array(3) {
["questionNumber"]=>
string(1) "1"
["questionText"]=>
string(35) " A car averages 27 miles per gallon"
["options"]=>
array(1) {
["a"]=>
string(8) "$44.44 b"
}
}
[2]=>
array(3) {
["questionNumber"]=>
string(1) "2"
["questionText"]=>
string(96) " When x = 3 and y = 5, by how much does the value of 3x2 – 2y exceed the value of 2x2 – 3y ?"
["options"]=>
array(3) {
["a"]=>
string(1) "4"
["b"]=>
string(2) "14"
["c"]=>
string(2) "16"
}
}
}
As you can see, the current output does not match - not by far, what I am trying to obtain.
Thank you in advance.
Hellow,
^[0-9]+\. (.*)[\r\n]+a\)[\s]+(.*)[\s]+b\)[\s]+(.*)[\s]+c\)[\s]+(.*)[\s]+d\)[\s]+(.*)[\s]+e\)[\s]+(.*)[\s]*
Try it !
$re = '/^[0-9]+\. (.*)[\r\n]+a\)[\s]+(.*)[\s]+b\)[\s]+(.*)[\s]+c\)[\s]+(.*) [\s]+d\)[\s]+(.*)[\s]+e\)[\s]+(.*)[\s]*/m';
$str = '1. A car averages 27 miles per gallon. If gas costs $4.04 per gallon, which of the following is closest to how much the gas would cost for this car to travel 2,727 typical miles?
a) $44.44 b) $109.08 c) $118.80
d) $408.04 e)
$444.40
2. When x = 3 and y = 5, by how much does the value of 3x2 – 2y exceed the value of 2x2 – 3y ?
a) 4
b) 14
c) 16
d) 20 e) 50';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
// Print the entire match result
var_dump($matches);

PHP Excel ( PHPExcel_IOFactory ) encoding issue

Thanks in advance.
Im uploading a .csv file through php 5.5 script that converts it from Unicode to UTF-8 and finally saves it on a folder.
Then i read this file with PHPExcel_IOFactory and capture some data to an array. So far so good. File uploads and saves ok, but something may be messing the data in the conversion process, because im getting the text strings in the array filled with blank spaces like this:
array(20) {
["A"]=>
string(39) "
l : 1 7 0 4 8 0 8 8 8 6 4 9 2 3 5 9 "
["B"]=>
string(51) " 2 0 1 7 - 0 8 - 0 9 T 0 0 : 2 1 : 5 7 + 0 2 : 0 0 "
["C"]=>
string(41) " a g : 2 3 8 4 2 6 1 5 5 8 3 3 9 0 2 5 8 "
["D"]=>
bool(false)
["E"]=>
string(41) " a s: 2 3 8 4 2 6 1 5 5 8 3 3 7 0 2 5 8"
["F"]=>
string(29) " D E S A R R O L L O W E B "
Maybe its because Delimiters. Opening .csv on sublime reveals two 'white spaces' as delimiters, so if i pass something like this :
$objReader->setDelimiter(' ');
It works and reads data, but filled with empty spaces. Some tip about how to get clean data from file?
NOTE: Using WAMP its working ok converting the file like this:
$conversion = iconv(mb_detect_encoding($conversion, mb_detect_order(),
true), "UTF-8", $conversion);
In production environment not working at all with that conversion (File saves empty)
Finally sorted out the problem. For anyone using PHPExcel and having same issue on character codification, if you really need to save the .xls file on a different character set, try something like this on the conversion:
$objReader->setDelimiter("\t");
$inputFileName = array_shift($inputFileNames);
$conversion = file_get_contents($inputFileName);
$conversion = iconv("WINDOWS-1252", "UTF-8", $conversion);
Thanks!

PHP - Read a result txt file to get vars

what I'm trying to do looks impossible with my actual PHP skills. Below you can find an exemple of a race result file, in txt. This file is composed of :
dir= the-track-file-name
longname= the-track-long-name-with-spaces
firstlap= the number of gate (checkpoint) the first lap is composed of
normallap= the number of gate (checkpoint) other laps are composed of
holeshotindex= thefirst gate after the start, which determine which player started first
time= the race duration, in minutes
laps= the number of laps (if minutes + laps, laps are counted when time's up)
starttime=1793
date= timestamp of the start
players:(under this line are all the player, just 1 in this exemple)
slot=0 (this is the multiplayer server slot taken by the player)
uid=5488 (this is the unique ID of the player)
number=755 (player's race number)
bike=rm125 (player's motorbike model)
name=Nico #755(player's name)
times: (under this line are things like timestamps of every gate, like SLOT|GATE|TIME)
0 0 1917 (it's like divide the timstamp /128 sounds good)
0 1 2184
(and etc, see full exemple below...)
The game server is on a dedicated ubuntu.
At each race end I send these results on an FTP web server, and what I need is to get vars to output something readable like a table with results after selecting a race (in a dropdown list i.e.).
Doing the table isn't the problem.
My problem is, even searching a lot here, that I don't know how to read the txt to obtain this kind of page (only RESULTS table) : http://mxsimulator.com/servers/q2.MXSConcept.com/races/6015.html
Here is a full sample result file : http://www.mediafire.com/view/3b34a4kd5nfsj4r/sample_result_file.txt
Thank you
Ok, tonight it's file parsing time.
I've written a very basic parser, which walks through the data line by line.
First it looks for "=". When a "=" is found the line is split/exploded at "=".
You get two parts: before and after the "=".
I've used them as key and value in an $results array.
This process continues till we reach the line "times:".
That's the line indicating that on the next line (line "times:" + 1) the results start.
The results are "slot gate time" separated by spaces. So the results are exploded with " " (space) this time and you get the three parts.
I've inserted an array key 'times' which contains an array with named keys (slot,gate,time).
You might just look at the structure of the $results array.
It should be very easy to iterate over it to render a table or output data.
#$datafile = 'http://www.mediafire.com/view/3b34a4kd5nfsj4r/sample_result_file.txt';
#$lines = file_get_contents($datafile);
$lines = '
dir=Dardon-Gueugnon
longname=Dardon Gueugnon
firstlap=72
normallap=71
holeshotindex=1
time=0
laps=6
starttime=1846
date=1407162774
players:
slot=0
uid=8240
number=172
bike=rm125
name=Maximilien Jannot | RH-Factory
slot=1
uid=7910
number=666
bike=rm125
name=Patrick Corvisier|Team RH-Factory
slot=2
uid=10380
number=114
bike=rm125
name=Benoit Krawiec | MXS-Concept.com
slot=6
uid=6037
number=59
bike=rm125
name=Yohan Levrage | SPEED
slot=8
uid=6932
number=447
bike=rm125
name=Morgan Marlet | Mxs-Concept.com
times:
6 0 1974
1 0 1989
0 0 2020
2 0 2056
6 1 2242
1 1 2260
0 1 2313
2 1 2338
6 2 2434
1 2 2452';
$results = array();
$parseResults = false;
#foreach($lines as $line){ // use this line when working with file_get_contents
foreach(preg_split("/((\r?\n)|(\r\n?))/", $lines) as $line){
if($parseResults === true) {
$parts = explode(' ', $line); // SLOT|GATE|TIME = parts 0|1|2
$times = array(
'slot' => $parts[0],
'gate' => $parts[1],
'time' => $parts[2]
);
$results['times'][] = $times;
}
if(false !== strpos($line, '=')) { // if line has a = in it, explode it
$parts = explode('=', $line);
$results[$parts[0]] = $parts[1]; // assign parts to array as key=value
}
if(false !== strpos($line, 'times:')) {
// we reached "times:", let's set a flag to start reading results in the next iteration
$parseResults = true;
}
}
var_dump($results);
Output:
array(15) {
["dir"]=> string(15) "Dardon-Gueugnon"
["longname"]=> string(15) "Dardon Gueugnon"
....
["name"]=> string(31) "Morgan Marlet | Mxs-Concept.com"
["times"]=> array(10) {
[0]=> array(3) { ["slot"]=> string(1) "6" ["gate"]=> string(1) "0" ["time"]=> string(4) "1974" }
[1]=> array(3) { ["slot"]=> string(1) "1" ["gate"]=> string(1) "0" ["time"]=> string(4) "1989" }
[2]=> array(3) { ["slot"]=> string(1) "0" ["gate"]=> string(1) "0" ["time"]=> string(4) "2020" }
...
} } }

$n = 2; 10-$n = 87

well this is what i am doing:
$total = (array_sum($odds))+$evens;
$total = str_split($total);
echo 'total[1]: '.$total[1].'<br />';
echo '10-$total[1]: ' . (10-($total[1]));
and the output is:
total[1]: 2
10-$total[1]: 87
my guess is it is being treated as a string, but how do i fix it?
so, what i want to know is
wh does (10-($total[1])); = 87?
Update:
yeah my mistake, a phantom 7,
but can anyone now tell me why:
echo $flybuys.' % '.$check.'<br />';
   $res = $flybuys % $check;
   echo 'res: '.$res;
outputs:
6014359000000928 % 8
res: 7
The inaccurate modulus result is because 6014359000000928 (~2^52) is beyond the bounds of an int, so PHP interprets it as a float. That implies you have a 32-bit system (PHP data type sizes vary depending on architecture). If you need to do math on large numbers, you can use a library like GMP. E.g.:
$flybuys = gmp_init("6014359000000928");
$res = gmp_mod($flybuys, 8);
Make sure you pass large numbers to GMP as strings.
If it is getting recognized as a string you could try casting it to an int using
(int)$total[1];
To be honest, you could probably cast the $total array into an int right when you do the string split:
(int)$total = ...;
Strings that represent numbers can also be cast into (float), and depending on which version of php you have (double).
Couldn't reproduce this issue:
$total = 2222; // some imaginary number as I don't know your $odds and $evens;
$total = str_split($total);
var_dump($total);
/*
*array(4) {
* [0]=>
* string(1) "2"
* [1]=>
* string(1) "2"
* [2]=>
* string(1) "2"
* [3]=>
* string(1) "2"
*}
*/
var_dump($total[1]);
/*
* string(1) "2"
*/
var_dump((10-($total[1])));
/*
* int(8)
*/
Absolutely the expected behavior...
I added this as an answer because in a comment is not enough space:
If this is the implementation of the algorithm described here i really think that modulo check 6014359000000928 % 8 == 0 shouldn't be there.
For example consider the number with the first 15 digits like that: 6014 3590 0000 062. For that evens is 15, odds is 24, total is 39 and check is 1. Any number modulo 1 is 0. So 6014 3590 0000 0628 is valid as 6014 3590 0000 0620 is or 6014 3590 0000 0627. That doesn't make sense.
I think you have to check the last digit for equality with check. In that case only 6014 3590 0000 0621 would be valid.

What is the equivalent of var_dump() in R?

I'm looking for a function to dump variables and objects, with human readable explanations of their data types. For instance, in php var_dump does this.
$foo = array();
$foo[] = 1;
$foo['moo'] = 2;
var_dump($foo);
Yields:
array(2) {
[0]=>
int(1)
["moo"]=>
int(2)
}
A few examples:
foo <- data.frame(1:12,12:1)
foo ## What's inside?
dput(foo) ## Details on the structure, names, and class
str(foo) ## Gives you a quick look at the variable structure
Output on screen:
foo <- data.frame(1:12,12:1)
foo
X1.12 X12.1
1 1 12
2 2 11
3 3 10
4 4 9
5 5 8
6 6 7
7 7 6
8 8 5
9 9 4
10 10 3
11 11 2
12 12 1
> dput(foo)
structure(list(X1.12 = 1:12, X12.1 = c(12L, 11L, 10L, 9L, 8L,
7L, 6L, 5L, 4L, 3L, 2L, 1L)), .Names = c("X1.12", "X12.1"), row.names = c(NA,
-12L), class = "data.frame")
> str(foo)
'data.frame': 12 obs. of 2 variables:
$ X1.12: int 1 2 3 4 5 6 7 8 9 10 ...
$ X12.1: int 12 11 10 9 8 7 6 5 4 3 ...
Check out the dump command:
> x <- c(8,6,7,5,3,0,9)
> dump("x", "")
x <-
c(8, 6, 7, 5, 3, 0, 9)
I think you want 'str' which tells you the structure of an r object.
Try deparse, for example:
> deparse(1:3)
[1] "1:3"
> deparse(c(5,6))
[1] "c(5, 6)"
> deparse(data.frame(name=c('jack', 'mike')))
[1] "structure(list(name = structure(1:2, .Label = c(\"jack\", \"mike\""
[2] "), class = \"factor\")), .Names = \"name\", row.names = c(NA, -2L"
[3] "), class = \"data.frame\")"
It's better than dump, because dump requires a variable name, and it creates a dump file.
If you don't want to print it directly, but for example put it inside a string with sprintf(fmt, ...) or a variable to use later, then it's better than dput, because dput prints directly.
print is probably the easiest function to use out of the box; most classes provide a customised print. They might not specifically name the type, but will often provide a distinctive form.
Otherwise, you might be able to write custom code to use the class and datatype functions to retrieve the information you want.

Categories