#Custom function to pack our arguments for BOFs
#Usage: Call it the same way you would call bof_pack 
sub custom_pack {
    local('$beaconId $formatString $formatStringFixed @argsFixed $totalSize $shiftCounter $index $binarySize $packedData')
    
    #We don't really need this but keeping it so the calling convention is the same
    $beaconId = $1;

    #Our original format string
    $formatString = $2;

    #Format string placeholder since we need to modify the values
    $formatStringFixed = '';

    #Drop the beacon ID and format string from our args, so that we just have the args to be packed
    #We could add a flatten call here if we wanted to pass in an array in the args too
    @argsFixed = sublist(@_, 2);

    #Calculate our total size, which gets packed at the end
    $totalSize = 0;
    
    #Whenever we add an item to the list we need to keep track of that to keep referencing the correct index
    $shiftCounter = 0;

    #Iterate through our format string and access the relevant data to be packed
    for ($index = 0; $index < strlen($formatString); $index++){
        #If we have an int
        if((charAt($formatString, $index) cmp "i") == 0){
            $totalSize += 4;
            $formatStringFixed = $formatStringFixed . 'i';
        }
        #If we have a short
        if((charAt($formatString, $index) cmp "s") == 0){
            $totalSize += 2;
            $formatStringFixed = $formatStringFixed . 's';
        }
        #If we have binary data
        if((charAt($formatString, $index) cmp "b") == 0){
            $binarySize = strlen(@argsFixed[$index + $shiftCounter]);
            $totalSize += $binarySize; #Size of our binary data
            #We need to pack the size of the data ahead of the data
            $formatStringFixed = $formatStringFixed . 'i';
            add(@argsFixed, $binarySize, $index + $shiftCounter);
            $shiftCounter++;
            #Z indicates that we'll specify how many bytes to read
            $formatStringFixed = $formatStringFixed . 'Z' . $binarySize; 
        }
        #If we have a normal string
        if((charAt($formatString, $index) cmp "z") == 0){
            $totalSize += strlen(@argsFixed[$index + $shiftCounter]) + 1; #Size of the string + a null terminator
            #We need to pack the size of the string ahead of the actual string
            $formatStringFixed = $formatStringFixed . 'i';
            add(@argsFixed, strlen(@argsFixed[$index + $shiftCounter]) + 1, $index + $shiftCounter);
            $shiftCounter++;
            #z is read characters until null byte
            $formatStringFixed = $formatStringFixed . 'z'; 
        }
        #If we have a wide string
        if((charAt($formatString, $index) cmp "Z") == 0){
            $totalSize += strlen(@argsFixed[$index + $shiftCounter]) * 2 + 2; #Size of the string + a null terminator (2 since it's UTF-16)
            #We need to pack the size of the string ahead of the actual string
            $formatStringFixed = $formatStringFixed . 'i';
            add(@argsFixed, strlen(@argsFixed[$index + $shiftCounter]) * 2 + 2, $index + $shiftCounter);
            $shiftCounter++;
            #u is read UTF-16 characters until null byte, and it needs to be little endian
            $formatStringFixed = $formatStringFixed . 'u-'; 
        }
    }

By admin

Leave a Reply

Your email address will not be published.