This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LAUNCHCC3220MODASF: snprintf Null pointer and multithreading

Part Number: LAUNCHCC3220MODASF

Hello everyone,

I use the CCS11 and the SDK 5.30.

I have two questions about the snprintf function coming with the compiler in CCS11.

1. Multithreading

As far as I know snprintf is thread safe in the very most implementation.

I inspected that the snprintf calls the function _PRINTFI that also uses only locale variables.
I also found the following comment in the description of _PRINTFI.

/*   For multi-threaded applications, when this function is called on       */
/*   behalf of fprintf, printf, vfprintf, or vprintf, the call site should  */
/*   be enclosed in a critical section that guarantees single-threaded      */
/*   access to the file stream.

So I assume that TI implementation for snprintf is thread safe too.
I am right?

2. Null pointer as destination buffer

The following lines shows a sampe code, that reads, writes the address zero and calls snprintf with a NULL pointer as destination buffer.

  {
    #define ADR0 (*(volatile uint32_t *)(0x0000))
    uint32_t u32_Value = ADR0;
    LOG_INFO( "read adr 0: 0x%x", u32_Value );

    ADR0 = 0x12345678;
    u32_Value = ADR0;
    LOG_INFO( "read adr 0 after write 0x12345678: 0x%x", u32_Value );
    ADR0 = 0x12345678;

    i32_Result = snprintf( (char*)NULL, (size_t)64, "TestString" ); // strlen = 10
    LOG_INFO( "format 0: returns %d", i32_Result );
  }

Result:

read adr 0: 0x20004000
read adr 0 after write 0x12345678: 0x20004000
format 0: returns 10

As far as I know the behavior ot the snprintf is conform to C99.

But I am wondering that the writes, starting at address NULL really takes place (see picture).

The address NULL seems to be the mapped first ROM address containing the start of the stack.

I assume that the writes to address NULL are ignored because the memory protection is not active.

Was it planned in that way?
Will that behavior be the same in TIRTOS 7?

Best regards,
Roman

  • Hi Roman,

    I'll follow up here tomorrow.

    Thanks,
    Jacob

  • Hi Roman,

    This question is better suited for the Compiler team; I am moving this question to them. Please expect a response within a couple of days.

    Thanks,
    Jacob

  • I assume that TI implementation for snprintf is thread safe too.
    I am right?

    The function snprintf is thread safe in the same way that strcpy is thread safe.  It does not touch any global state, unless the user passes in the address of something in the global state as an argument.

    Null pointer as destination buffer

    The function snprintf presumes the destination buffer is safe to write to, unless the second argument (the limit on the number of bytes to write) is 0.  As you have demonstrated, if NULL is passed, then the code attempts to write to address 0.  

    I assume that the writes to address NULL are ignored because the memory protection is not active.

    That is a device specific question that I lack the expertise to answer.  I will notify the device experts about this part of your question.

    Thanks and regards,

    -George

  • Hi Roman,

    I'll follow up on the other question next week.

    Thanks,
    Jacob

  • Hi Roman,

    I assume that the writes to address NULL are ignored because the memory protection is not active.

    You are correct; there is no memory protection on address 0x0. However, the write does not take effect in this place because it is reserved by the device. You are only able to write to the device's RAM. I do not expect this to change with TI-RTOS 7 because it is device-specific behavior.

    Thanks,
    Jacob

  • Thank Jacob,

    in my opinion there is still a risc if the buffer size parameter of snprintf is corrupted to a very high value, leading to an ongoing walk starting at address zero.

    E.g. a (of course wrong) conversion of the from a negative int to size_t that is not checked by the programmer.

    Because there is no MPU and no NULL pointer check it could be a long address walk, that will/ could arrive at registers or memory addresses ;)

    Best regards,
    Roman

  • Hi Roman,

    Are you able to evidence of this behavior? Perhaps you could provide a use case that demonstrates reading reserved sections of memory. If you are successful, then you could submit a potential vulnerability here.

    Thanks,
    Jacob

  • Hello Jacob,

    thanks for your information. I will try to evidence and if it occurs as I expected, I will follow your link.

    Many thanks,
    Roman