Using floating point format specifiers can cause system crashes

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Using floating point format specifiers can cause system crashes

1,829 Views
BryGuyH
Contributor IV

I noticed this issue. I have submitted it to Freescale already but I thought it would be good to also provide this information for users of MQX that may be using floating point in their applications. This affects all platforms since it is in device independent PSP code.

Summary of Problem:

Floating point specifiers in print statements (%f, %e, %g) are

currently unsafe and can potentially cause system corruption

and sporadic crashes.

File: io_fp.c

Function: _io_cvt

Line: 482 - *--p1 = (char)((uint_32)tmpintpart + '0');

In this case p1 is decremented from the end of the buffer through

the beginning and further up the stack until it collides with

something that will cause system stability problems (like the

return pointer and saved registers) since NDIG is defined as 154

on line 78 of fpio_prv.h

A couple ways to prevent this crash:

#define NDIG (3 + MANT_BITS + EXP_BIAS)

i.e. 1078 bytes which will mean you'll have to likely bump your task stacks from whatever they are by an additional 900 bytes.

Or coerce your variable into floats prior to passing them into the print statements.

0 Kudos
5 Replies

1,002 Views
lorenzofornari
Contributor III

i have the same problem, but nor force casting neither increase NDIG worked for me...

0 Kudos

1,002 Views
BryGuyH
Contributor IV

Your task stack sizes may be too small. I've found on our system we have to specify a minimum of 1200 bytes for a stack size on every task that simply calls printf (or any other formatted i/o function)

Of course that minimum would be smaller if you don't compile MQX with floating point i/o support - but you would still experience crashes if your stacks were smaller than the minimum required by the formatted i/o functions. Depending on your toolchain you'll have to get the stack depth for each of your tasks, you can get this from some profiling tools. For Keil uVision I look at the static call graph and add 25%

0 Kudos

1,002 Views
lorenzofornari
Contributor III

i don't know why, but i solved importing all my code into an example project...

If i create a new mqx 4 project, i found no way to print float.

I started from an example project (i tried with both "io" and "hmi" for twrk70), i deleted all code, renamed it, copied all my code, modified linked resources and includes path to fit with my previous... and it works.

:smileyshocked:

Moreover: i had a problem with eGui, since i can't write unsigned chars into label objects, eg "à" that is 0xE0.

Now i can without any change....

:smileyshocked::smileyshocked::smileyshocked:


Moral of the story: never start a new project (copy an existing one).

0 Kudos

1,002 Views
c0170
Senior Contributor III

Hello Bryan Hunt,

thank you for sharing this here on the community. Why did you expand NDIG define to 1078? Isn't that double precision, single should be as is set, 153 digits.

Can you share a small snippet which would cause the stack corruption thus can be tested.

Regards,

c0170

0 Kudos

1,002 Views
BryGuyH
Contributor IV

That is correct that is for double precision. All the MQX formatted i/o functions are written using "double" instead of "float" (given the ansi definition doesn't make a distinction %f, %e, %g are suppose to operate on both equally). The functions do not check whether or not an incoming value will induce a crash (which would be another, albeit less desirable,  fix than simply modifying the algorithm to not need a temp buffer to hold all digits of a number of which only 6 significant figures would be printed. This is why I said one work around would be to coerce values to float prior to sending them into the printf statement:

double value = 1.5e170;

printf("%g\r\n", value);    //will cause a crash by overwriting the _io_cvt stack (specifically the return pc)

printf("%g\r\n", (float)value); //will prevent the crash from occuring

I have tested a few small values (e.g. 1.5e-170 & 1.5e-1077) and they do not appear to cause a crash, but I didn't run a comprehensive series of test to conclude the extremely small values don't have a possible buffer overrun as well. It is possible that %f may cause one.

0 Kudos