[BUG] Function unsigned_to_hex_string() does not zero pad

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
GrBa_3483646
Level 3
Level 3
First like received First like given

WICED-Studio-6.2.1

in /43xxx_Wi-Fi/WICED/internal/wiced_lib.c

function unsigned_to_hex_string()

The function does not zero pad the output string which leads to uninitialized parts of the output string.

Found by testing /43xxx_Wi-Fi/apps/demo/bt_internet_gateway/restful_smart_server.

0 Likes
1 Solution

Any parameter which should result in zero padding has the problem.

e.g. use:

int value = 0xB; char* string = (char*)malloc(sizeof(ULONG_MAX_STR) + 1); unsigned_to_hex_string( value , string, 4, 4 ); WPRINT_APP_INFO((" %s\n", string));

This should result in "000B".

I explain what happens (source below).

  1. digits_left will be 4
  2. the conversion loop runs for all 4 digits or aborts on zero value (which is the case in our example after first digit)
  3. because the loop has only set 1 digit of buffer[], the rest of buffer[] is uninitialized!
  4. unintialized data is returned

In old SDK 5.x the local buffer was initialized with "00000000" and therefor the loop worked.

/**  * Converts a unsigned 32-bit long int to a hexidecimal string  *  * @param value[in]      : The unsigned 32-bit long int to be converted  * @param output[out]    : The buffer which will receive the hexidecimal string. A terminating 'null' is added. Ensure that there is space in the buffer for this.  * @param min_length[in] : The minimum number of characters to output (zero padding will apply if required)  * @param max_length[in] : The maximum number of characters to output. The max number of characters it can have is of the length of (ULONG_MAX + 1).  *  * @note: No leading '0x' is added.  *  * @return the number of characters returned (excluding terminating null)  *  */ uint8_t unsigned_to_hex_string( uint32_t value, char* output, uint8_t min_length, uint8_t max_length ) {     uint8_t digits_left;     char buffer[sizeof(ULONG_MAX_STR) + 1]; /* Buffer for ULONG_MAX with +1 for storing the sign */     max_length = (uint8_t) MIN( max_length, sizeof( buffer ) );     digits_left = max_length;     while ( ( value != 0 ) && ( digits_left != 0 ) )     {         --digits_left;         buffer[ digits_left ] = nibble_to_hexchar( value & 0x0000000F );         value = value >> 4;     }      digits_left = (uint8_t) MIN( ( max_length - min_length ), digits_left );     memcpy( output, &buffer[ digits_left ], (size_t)( max_length - digits_left ) );      /* Add terminating null */     output[( max_length - digits_left )] = '\x00';      return (uint8_t) ( max_length - digits_left ); }

View solution in original post

7 Replies
PriyaM_16
Moderator
Moderator
Moderator
250 replies posted 100 replies posted 50 replies posted

Hello,

The function appears to be working correctly. It terminates the hex string by a NULL character. I checked by calling the function directly and passing integer value as argument.

int value = 100;

char* string = (char*)malloc(sizeof(ULONG_MAX_STR) + 1);

unsigned_to_hex_string( value , string, 2, 2 );

WPRINT_APP_INFO((" %s\n", string));


Can you point any specific use case where you passed an integer and the hex string is not null terminated?

0 Likes

riya​ You did not understand the problem.

This is zero termination: "100\0"

This is zero padding: "0001"

The problem is visible with restful_smart_server demo when the BLE scanned data is sent in response.

When Hex Data e.g. 0x0B should be converted you get: "?B\0" instead of "0B\0" because the zero padding does not work.

0 Likes

gregor.bader_3483646 wrote:

riya You did not understand the problem.

This is zero termination: "100\0"

This is zero padding: "0001"

The problem is visible with restful_smart_server demo when the BLE scanned data is sent in response.

When Hex Data e.g. 0x0B should be converted you get: "?B\0" instead of "0B\0" because the zero padding does not work.

Hi gregor.bader_3483646

Can you provide the parameters to pass to unsigned_to_hex_string() that can cause issue?

unsigned_to_hex_string( uint32_t value, char* output, uint8_t min_length, uint8_t max_length )

0 Likes

Any parameter which should result in zero padding has the problem.

e.g. use:

int value = 0xB; char* string = (char*)malloc(sizeof(ULONG_MAX_STR) + 1); unsigned_to_hex_string( value , string, 4, 4 ); WPRINT_APP_INFO((" %s\n", string));

This should result in "000B".

I explain what happens (source below).

  1. digits_left will be 4
  2. the conversion loop runs for all 4 digits or aborts on zero value (which is the case in our example after first digit)
  3. because the loop has only set 1 digit of buffer[], the rest of buffer[] is uninitialized!
  4. unintialized data is returned

In old SDK 5.x the local buffer was initialized with "00000000" and therefor the loop worked.

/**  * Converts a unsigned 32-bit long int to a hexidecimal string  *  * @param value[in]      : The unsigned 32-bit long int to be converted  * @param output[out]    : The buffer which will receive the hexidecimal string. A terminating 'null' is added. Ensure that there is space in the buffer for this.  * @param min_length[in] : The minimum number of characters to output (zero padding will apply if required)  * @param max_length[in] : The maximum number of characters to output. The max number of characters it can have is of the length of (ULONG_MAX + 1).  *  * @note: No leading '0x' is added.  *  * @return the number of characters returned (excluding terminating null)  *  */ uint8_t unsigned_to_hex_string( uint32_t value, char* output, uint8_t min_length, uint8_t max_length ) {     uint8_t digits_left;     char buffer[sizeof(ULONG_MAX_STR) + 1]; /* Buffer for ULONG_MAX with +1 for storing the sign */     max_length = (uint8_t) MIN( max_length, sizeof( buffer ) );     digits_left = max_length;     while ( ( value != 0 ) && ( digits_left != 0 ) )     {         --digits_left;         buffer[ digits_left ] = nibble_to_hexchar( value & 0x0000000F );         value = value >> 4;     }      digits_left = (uint8_t) MIN( ( max_length - min_length ), digits_left );     memcpy( output, &buffer[ digits_left ], (size_t)( max_length - digits_left ) );      /* Add terminating null */     output[( max_length - digits_left )] = '\x00';      return (uint8_t) ( max_length - digits_left ); }

Thanks, I got your point now.

I already fixed it locally when I upgrade to sdk-6.2. The bug is indeed in standard sdk-6.2.

0 Likes

Sir, We have created an internal ticket to take care of the issue. I will update the thread when the fix is available.

0 Likes
PriyaM_16
Moderator
Moderator
Moderator
250 replies posted 100 replies posted 50 replies posted

The buffer needs to be intialized with Zero and we have fixed this internally. The next release will not have this error.