Author Topic: [AVR] Buffer overflow leads to MCU reset - by what mechanism does this occur?  (Read 700 times)

0 Members and 1 Guest are viewing this topic.

Online HwAoRrDk

  • Frequent Contributor
  • **
  • Posts: 742
  • Country: gb
Yesterday I encountered and fixed a bug in some AVR code of mine. It was a pretty stupid bug: I neglected to check the number of bytes I was telling memset() to operate on. The line of code was as follows:

Code: [Select]
memset(&foo[foo_len], 0x00, foo_max - foo_len);

Fairly straightforward - I wanted to fill the remaining space in an array with zeros. Except, a mistake in a preceding line of code made foo_len in certain circumstances have a value one larger than foo_max. Whoops, my calculated size value is negative and just got wrapped around into a large positive integer, so I just asked memset() to write to 65,535 bytes of memory! :scared:

Unsurprisingly, this did not have positive effects. ;D The AVR microcontroller crashed and reset. What I am curious to learn is by what mechanism the reset occurred.

If I had to make an educated guess, I would say that writing zeros to RAM proceeded unimpeded all the way to the end of the address space (2K RAM on the part I'm using, so address 0x08FF according to the datasheet) and then wrapped around to the beginning, where it trampled on the CPU registers, which is what caused the reset. Perhaps because the execution pointer got written to zero, so effectively jumping to the start of program memory?

I would be interested to hear whether my guess is correct.
 

Offline tsman

  • Frequent Contributor
  • **
  • Posts: 595
  • Country: gb
You'll have overwritten the stack which is at the end of RAM and grows backwards. The return address is kept there so when it pops that off the stack it'll jump to the reset vector at 0x0000.

The PC and SP registers aren't kept in data memory.
 

Online HwAoRrDk

  • Frequent Contributor
  • **
  • Posts: 742
  • Country: gb
Oh, okay, that makes sense. I was thinking writing past the end of RAM would wrap and nobble the stack pointer registers, but if not I guess post-memset() execution returning to location 0x0000 would make it seem like a reset had occurred. :)
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 509
Its been a long time, but the mega88, mega16 act as follows (newer ones act possibly the same)-

if using an xyz pointer or lds/sts- if the address is greater than sram end, the resulting address will be in sram
example- mega88 with RAMEND=0x4FF, 11bit addresses (0x7FF)
if address > RAMEND then addressH = addressH & 7 - RAMENDH
so for address of 0x623, actual address is 0x223 (6 & 7 = 6, 6 - 4 = 2, addressH = 2)

stack pointer will act the same, in addition the stack pointer does nothing on a push to an address below sram, and a pop below sram will pop a value of 0

if you have a debugger you can verify this (if curious)
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf