0

I try to understand what data types are read from a byte array. These methods seem to follow a common pattern:

public class Reader {

    static short readA(byte[] bytes, int i) {
        int s = ((((short) bytes[i]) & 255) << 8)
                | (((short) bytes[i + 1]) & 255);
        return (short) s;
    }

    static int readB(byte[] bytes, int i) {
        return ((bytes[i] & 255) << 8)
                | (bytes[i + 1] & 255);
    }

    static int readC(byte[] bytes, int i) {
        return ((bytes[i] & 255) << 24)
                | ((bytes[i + 1] & 255) << 16)
                | ((bytes[i + 2] & 255) << 8)
                | (bytes[i + 3] & 255);
    }

}

Does readC read a signed integer? Does readB read a signed short? What does readA read?

  • 2
    I think that your question isn't related to reverse engineering. Nonetheless, readA returns short created as concatenation of bytes[i] and bytes[i+1] (i.e. if bytes[i]=00000010 and bytes[i+1]=10000011, it will return 10100000011). readB returns the same except that will be of type int, while readC returns an int representing concatenation of bytes[i], bytes[i+1], bytes[i+2] and bytes[i+3]. – bart1e Aug 25 '19 at 10:44
  • assume i = 0 bytes = [1,2,3,4] so bytes[0] is the first byte in array it is left shifted by 8 so 1 << 8 == 256 | 2 == 258 the & 255 is there to take only the byte from input ie instead of [1,2,3,4] the input can be [0x8097abef,....] the & 255 will strip the 8097ab an will take only ef for left shifting ie ef << 8 ie the result will be 0xef00 | yy – blabb Aug 25 '19 at 11:23
  • @bart1e please put answers in the answer box, not in comments. Thanks – Igor Skochinsky Aug 25 '19 at 13:05
  • @blabb as well. – Igor Skochinsky Aug 25 '19 at 13:06
  • 1
    understanding code is also reverse engineering, this question is not necessarily offtopic here – Igor Skochinsky Aug 25 '19 at 16:22
2

Lets Break the algo into pieces before trying to understand

the algo is broken into pieces using bodmas (bracket open ,divide ,multiply ,add, subtract )

and/or Operator precedence

lets take the uncasted readB first

static int readB(byte[] bytes, int i) {
    return ((bytes[i] & 255) << 8)
            | (bytes[i + 1] & 255);
}

prototype of function says it takes an array of bytes and an integer does some thing and returns an int back

static int readB(byte[] bytes, int i)

body of the function (where it does the aforementioned something

return ((bytes[i] & 255) << 8) | (bytes[i + 1] & 255);

there are two bracketed expression one of which has a child

1. ((bytes[i] & 255) << 8)    
          I. (bytes[i] & 255)
 3. (bytes[i + 1] & 255)  

breaking the child expression apart it has three components a constant 255 and two variables
which are arguments or inputs provided to the function
the byte array bytes[] and
the integer i
since i is an int the array can range from 0 to 2^31 -1

( think what will happen if you provide a null array or
an array with just 1 value or an array with 2^31-1 values
or int >= array size
(bounds checking
this link has the following code check the results and see the thrown exception

{  
    static byte foo[] = {1,2,3,4,5,6,7,8 };
    static int readB(byte[] bytes, int i)
    {
        return ((bytes[i] & 255) << 8) | (bytes[i + 1] & 255);
    }
    public static void main(String args[])
    {
        for(int i = 0; i < foo.length ; i++ ) 
        {
            System.out.printf("bounds check %d %d %d\n" , i , foo[i] , readB(foo,i));
        }
    }
}

result of running the code

Compilation time: 1.05 sec, absolute running time: 0.22 sec,  
cpu time: 0.15 sec, memory peak: 18 Mb, absolute service time: 1,27 sec

Error(s), warning(s):

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 8
    at Rextester.readB(source.java:12)
    at Rextester.main(source.java:18)

bounds check 0 1 258
bounds check 1 2 515
bounds check 2 3 772
bounds check 3 4 1029
bounds check 4 5 1286
bounds check 5 6 1543
bounds check 6 7 1800

)

bytes[i] & 255

this actually is superfluous operation

the bytes[i] array is already of BYTE type so the values can never exceed 255 and there is no point stripping the rest this would only make sense if the type is > BYTE like WORD foo[] which can hold anything from 0x0000 to 0xffff or int foo[] which can hold anything from 0x00000000 to 0xffffffff so stripping the hibyte and highwords may make sense .

in this specific code we can safely ignore this

so basically it takes two bytes from the given position and folds them into a bigger type
so readA returns a SHORT and readB returns and INT type

ie readA takes two bytes from a give position and folds it into anything between 0x0000 and 0xffff readB takes two bytes from a given position and folds into anything between 0x00000000 and 0xffffffff (actually it is same as 0x00000 and 0xffff if not for size of type calculation or pointer arithmetic's )

the third readC now should be clear enough for you ittakes 4 bytes and folds it into anything between 0x00000000 and 0xffffffff (this function utilizes the whole range not unlike the readA() / readB()

see the shifts 24,16,8 which puts
byte[ position 1] at 0xAA-??????
byte[ position 2] at 0xAA-BB-????
byte [position 3] at 0xAA-BB-CC-?? and
byte [position 4] at 0xAA-BB-CC-DD
and returns back 0xAABBCCDD

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.