Negative number causes VarInt's encoding function to crash - python

I try to implement the function below in Python but as soon as I enter a negative number the function crashes. Does anyone understand why?
public static void writeVarInt(int value) {
do {
byte temp = (byte)(value & 0b01111111);
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
}
writeByte(temp);
} while (value != 0);
}
Here my function :
def write_varint(array, data):
first_pass = True
while data != 0 or first_pass:
first_pass = False
temp = (data & 0b01111111)
data >>= 7
if data != 0:
temp |= 0b10000000
print(temp)
write_byte(array, temp)
def write_byte(array, data):
write_bytes(array, struct.pack('>b', data))
def write_bytes(array, source_bytes):
for byte in source_bytes:
array.append(byte)

if data != 0:
temp |= 0b10000000
When data value is -1 this conditional does not get called and therefore temp ends up out of range of the needed [-128, 127], and wounds up crashing when struct.pack() function gets called (which requires a number within that range).

Related

Given a C++ file with many function definitions, how to get the starting and ending index of a particular function using Python?

The purpose is to comment the entire function void test_func with many nested {} using Python.
file = open(path_of_file)
data = file.readlines()
for item in data:
if item.find('void test_func') != -1:
point = data.index(item)
data.insert(point, '/*')
stack = []
for i in data[point+1:]:
if i.find('{') != -1:
stack.append('{')
elif i.find('}') != -1:
stack.pop()
if len(stack) == 0:
point1= data.index(i)
data.insert(point1+1,'*/')
Using the find() method I can find the starting index of the function while iterating over the lines. I was trying to use the balanced parenthesis method, to reach the end of the function, So when my stack is empty I will reach the end of the test_func.
This is not working in this example:
void test_func(arguments,\
arguments)
{
It is inserting */ just after the line:
/*void test_func(arguments,\
*/arguments)
{
Assuming that a "}\n" line only happens at the end of a function and always happens at the end of a function, you want something like:
in_func = False
for line in file.readlines():
line = line.strip('\r\n') # remove line breaks since print will add them
if in_func:
print("// " + line)
if line == "}":
in_func = False
elif line.startswith('void test_func('): # paren required to not match test_func2
print("// " + line)
in_func = True
else:
print(line)
Assuming that both ( / ) pairs and { / } pairs are balanced, you can look for the ) that balances the parameter list's ( and then the } that balances the body's first {.
We want to ensure that void test_func() {} etc is also caught, so I've pulled out the checks into local functions, so we start looking on the same line for the next pair of characters.
file = open(path_of_file)
data = file.readlines()
start = None
params = None
body = None
open = 0
close = 0
for index, line in enumerate(data):
def balanced(o, c):
open += line.count(o)
close += line.count(c)
return open > 0 and open = close
def checkBody():
if balanced('{', '}'):
body = index
def checkParams():
if balanced('(', ')'):
params = index
open = 0
close = 0
checkBody()
def checkStart():
if line.find('void test_func') != -1:
start = index
checkParams()
if start is None:
checkStart()
elif params is None:
checkParams()
elif body is None:
checkBody()
if start is not None and body is not None:
data.insert(start, '/*')
data.insert(body + 1, '*/')

Python read character

I would like to know how can I read the charaters into a buffer in Python?
In C code, I can easy decralare the buffer character like char buffer[256];:
void read_char(int x, char buffer[], int *flag_stop) {
int i, length;
char character;
i = 0;
bzero(buffer, 256);
do {
if ((length = read(x, &character, 1)) <= 0)
{
*flag_stop = 1;
break;
}
buffer[i] = character;
i++;
}
while(c != 0x0A);
}
But I don't know how to do in Python so the code is something like this:
def read_char(x,buffer,**flag_stop):
i = 0
buffer = np.array([], dtype='S64')
while True:
if os.read(x, character, 1) <= 0:
**flag_stop == 1
break
buffer[i] = str(character)
i=i+1
if(character != 0x0A):
break
I have tried with numpy.chararray but I did not work. Any idea for this problem? thank you very much!
Your main problem is that you want in Python write code exactly like in C.
Python would need something like this
def read_char(x):
flag_stop = False # or 0
i = 0
buffer = np.array([], dtype='S64')
while True:
character = os.read(x, 1)
if not character: # if len(character) < 0
flag_stop = True # or 1
break
buffer[i] = character
i += 1
if character != 0x0A:
break
return buffer, flag_stop
# ---
buffer, flag_stop = read_char(file_handler)
I don't like str() in your code - you may get single byte which is part of mulit-bytes code (like utf-8) and converting to str() can only mess it.

type error when casting sting type to integer type using python 3

I write code to achieve the effect like that if you write 123 then return 321, if -123 then return -321. However, after I finished the code and try to run it the sentence of | int = -int(rev_str) | gives me the error saying: "'int' object is not callable". I do not know why, please anyone help me. thank you so much and appreciate it.
def reverse_32_int(int):
if (int < -(2**31)) or (int > 2**31 - 1):
print('exceed 32-bit range')
else:
if int < 0:
int = -int
str_int = str(int)
rev_str = str_int[::-1]
int = -int(rev_str)
return int
elif int > 0:
str_int = str(int)
rev_str = str_int[::-1]
int = int(rev_str)
return int
else:
return 0
reverse_32_int(123)
You used int as variable in def reverse_32_int(int). You can't have variable int and function int(). Rename it.
I use variable value instead of int
def reverse_32_int(value):
if (value < -(2**31)) or (value > 2**31 - 1):
print('exceed 32-bit range')
else:
if value < 0:
value = -value
str_int = str(value)
rev_str = str_int[::-1]
value = -int(rev_str)
return value
elif value > 0:
str_int = str(value)
rev_str = str_int[::-1]
value = int(rev_str)
return value
else:
return 0
reverse_32_int(123)

Python - Ported AS2 function doesn't work

This game uses this encryption to stop people from being able to connect bots easily the function used by the game is:
function djinndecrypt(string, key) {
var crypt = "";
var part = "";
var parts = 0;
var keyGen = key.length;
for(var i = 0; i < string.length; i++) {
var char = string.charAt(i);
var chrNum = string.charCodeAt(i);
var keyChr = key.charAt(parts % key.length);
var keyNum = key.charCodeAt(parts % key.length);
part += char;
if((i+1) % 3 == 0 && i > 0) {
crypt += String.fromCharCode((coreHash.indexOf(part)+2) - keyNum - keyGen);
part = "";
parts++;
}
}
return crypt;
I have attempted to port this to python my code is:
coreHash = "4Qiqc3mpjw2jFLJBaV9ANsWoYDR8ktvZIMeJTfOd1lyH5P7XKxhU6rCbzuE10nS5Ks7rPj1YvnDlbX4m2jI0NkyOL3hHU6FRVduJJoCwfWiABzqSaETMet1pZ89xQc81ieHA0F5EuNnWCwJvMJLQhV3UxPYRB76pbfIy2dcoaT14XkqlZsSzj9KDtrmjO9fjdMPERB12TYzDJrNxc3QajKU0kbvu4F56yHAXWO7tlwni8mZqCSosLVIehJ1pzT1kEsSXAl1O45CdLnRwQeM06ZqxJfJayBN8FWj2prYjuKIhiHU7VbomDPvct935yULcOHNJZsa31DeSlmnPBxJkYbTdAFRotIizv2VpXuf9w0KqQ8Ehjr4MW7Cj164Y1ukWxp9EjOwDPF8rsX5vlZN7QJqfteCATKncUoLVaM16Shy";
def djinndecrypt(string, key):
crypt = ""
part = ""
parts = 0;
keyGen = len(key)
for i in xrange(len(string)):
char = string[i]
chrNum = ord(char)
keyChr = key[parts % len(key)]
keyNum = ord(keyChr)
part += char
if((i + 1) % 3 == 0 and i > 0):
crypt += chr((coreHash.find(part) + 2) - keyNum - keyGen)
part = ""
parts += 1
print crypt
djinndecrypt("zQDHzljoHM6RhuhuhWzQDA5dgOAzQDlbAqkgOA57mM", "69338277581336797325449966279465")
The code ends up raising an exception:
ValueError: chr() arg not in range(256)
chr() only accepts up to 255 as described by the error. You can get more distance using unichr() but that returns Unicode characters instead of ACSII like chr().
However, given that this is supposed to result in an English string, the problem appears to be in the coreHash, as results above 122 [ chr(122) is 'z' ] will be out of alphabetical range.

Idiomatic way to port C bitfiddling to Python

How would you port the following C code in a Pythonic way (especially the bit fiddling part in Get2, Get3, ...)
switch(mem[pos-1])
{
...
case 0x10: pos+=Get2(&mem[pos+0x02])+0x04; break;
case 0x11: pos+=Get3(&mem[pos+0x0F])+0x12; break;
case 0x16: pos+=Get4(&mem[pos+0x00])+0x04; break;
...
case 0x20: pos+=0x02; break;
}
...
//////////////////////////////////////////////////////////
// Conversion routines to fetch bytes in Big Endian order
//////////////////////////////////////////////////////////
unsigned int Get2(unsigned char *pointer)
{
return (pointer[0] | (pointer[1]<<8));
}
unsigned int Get3(unsigned char *pointer)
{
return (pointer[0] | (pointer[1]<<8) | (pointer[2]<<16));
}
unsigned int Get4(unsigned char *pointer)
{
return (pointer[0] | (pointer[1]<<8) | (pointer[2]<<16) | (pointer[3]<<24));
}
This is what I've got so far:
x = struct.unpack('B', mem[pos-1])[0]
if x == 0x10:
# pos += ???
continue
if x == 0x11:
# pos += ???
continue
if x == 0x16:
# pos += ???
continue
if x == 0x20:
pos += 0x02
continue
If you're just getting one unsigned byte, just do
x = ord(mem[pos - 1])
on Python 2 or
x = mem[pos - 1]
on Python 3.
Instead of select / case, You want a dictionary.
positions = {0x10: do_10, 0x11: do_12, 0x16: do_16}
Where do_10 etc. are functions:
def do_10(pos):
# This actually would need an endianness character
return struct.unpack('H', mem[pos + 0x02])[0] + 0x04
You use it like this:
pos += positions[mem[pos - 1]](pos)
If you want to define the functions right in the dictionary, you can:
positions = {
# This actually would need an endianness character
0x10: (lambda pos: struct.unpack('H', mem[pos + 0x02])[0] + 0x04)
# ...
}
This is a guess, but based on your code, I think this is what you're looking for:
x = struct.unpack('B', mem[pos-1])[0]
if x == 0x10:
pos += 0x04 + struct.unpack('>h' mem[pos+0x04])
elif x == 0x11:
pos += 0x12 + (0x00FFFFFF & struct.unpack('>i' mem[pos+0x0F]))
elif x == 0x16:
pos += 0x04 + struct.unpack('>i' mem[pos])
elif x == 0x20:
pos += 0x02
Your four bit-fiddlers could almost transliterated in python
def bigstr_to_int2(str) :
return (ord(str[0])<<8) | ord(str[1])
Seems to work, but is perhaps not "idiomatic". Ideally, you should try to use the struct.unpack to do the whole thing in bulk, but I can't tell you how to do that, because I don't understand the main function up the top.

Categories