char[] sigsegv?


eyecreate

Member
Joined
Feb 3, 2009
Messages
253
Website
git.eyecreate.org
I'm trying to compile a C program for the pandora. Doing some debugging, it seems to throw a sigsegv on function entering when the function has a char [] variable in it. Also, whenever I inspect using gdb command "info locals", most the variables in the function are empty, but the char[] variable has quite a lot of data listed for it. Any Ideas?
 


#define LEN 4096
char *do_things(void) {
char *happy = NULL;
char crash[LEN]; //comment me and any code using me out and I don't throw sigsegv
}
Code:
(gdb) info locals
happy = ""
crash = "\000\000\000\000\000\005\346\000\000"...


Library of code with issue: http://download.owncloud.com/download/ocsync-0.70.3.tar.bz2

GUI program on top I've been running: http://download.owncloud.com/download/mirall-1.2.0.tar.bz2

The spot identified by the compiler is in csync_mis.c : csync_get_user_home_dir

UPDATE:I've made a bug report on the dev's tracker in hopes they might be able to shed more light too:
https://github.com/owncloud/mirall/issues/400
 
Last edited by a moderator:
This is generic C/C++ stuff.

In your example, happy is a null pointer (to a char array if it werent null).

crash[] is an uninitialized array of chars.

GDB will always have all of those bytes to show, since it is inherently an array of 4096 chars allocated on the stack when you enter the function. Usually 4k of stack use for a function is a bit big, but that is not your crash reason.

I actually dont GDB much, but somehow happy = "" output sounds weird compared to the example "code"... I feel like it should say happy = <NULL> - but I dont gdb that much ...

The fact that the crash array is unitialized should not be un-noted, and you cant use the two things you list in your small example in the same fashion. But anyways, to diagnose more you should show us actual code.
 
Good to know the values were just gdb showing the uninitialized space and not some other problem. I don't usually use GDB outside an IDE. I'll link the code I was using in OP.
 
first, I'm curious ... what program are you working on?  :)   It's nice to see more and more people developing code for the Pandora...

This latest coding competition has been awesome... so many entries, nice apps, games, ports ...

I don't think that code would crash as it is ... looks ok to me.


But if you try to print or use the crash[] array as a string, without initialising it first, then it might perhaps crash.

More likely it would just print an empty or short garbage string, as the stack will typically contain plenty of '\0' bytes.

So anyway, you can do like this if you want to initialise a string:


char crash[LEN] = "";

or whatever ...
 
Last edited by a moderator:
first, I'm curious ... what program are you working on?  :)   It's nice to see more and more people developing code for the Pandora...

This latest coding competition has been awesome... so many entries, nice apps, games, ports ...

I don't think that code would crash as it is ... looks ok to me.


But if you try to print or use the crash[] array as a string, without initialising it first, then it might perhaps crash.

More likely it would just print an empty or short garbage string, as the stack will typically contain plenty of '\0' bytes.

So anyway, you can do like this if you want to initialise a string:


char crash[LEN] = "";

or whatever ...
Would have thought maybe initializing it would help but for two things. One, another later spot that causes this issue, if I comment out like I mentioned, is this line:


char errbuf[256] = {0};
which does initialize the variable. Second, The program runs fine on my desktop, so the issue is something specific to the pandora: maybe the compiler output or maybe the architecture's differences. (Also, I did try using the flag -fno-inline due to online suggestions of stack issues, but didn't see a difference.)

The program is a sync client for my server so I can have my files is sync between my devices. (http://owncloud.org/sync-clients/)
 
Last edited by a moderator:
The program runs fine on my desktop, so the issue is something specific to the pandora
Did you write this sync client, or you're building it?

I guess the code has a bug, but it happens to work anyway on the desktop at the moment. Perhaps they assumed something which is not true on ARM, or it might have a buffer overrun.

If I were you I would try to do a 'binary search' on the code, to look for the bug. Cut your code in half repeatedly, trying to keep the bug in it, until you get a minimal test case that shows the bug. Then we can easily see what's going wrong, and whether it's a bug in the program or perhaps (unlikely) a bug with the Pandora compiler or libs or whatever. But if you didn't write the program, you might not want to go to all that trouble.

I'm too lazy to try building this all by myself, but if you can post a tgz with the source and deps ready to run "make", I will try it.
 
Last edited by a moderator:
The program runs fine on my desktop, so the issue is something specific to the pandora
Did you write this sync client, or you're building it?

I guess the code has a bug, but it happens to work anyway on the desktop at the moment. Perhaps they assumed something which is not true on ARM, or it might have a buffer overrun.


If I were you I would try to do a 'binary search' on the code, to look for the bug. Cut your code in half repeatedly, trying to keep the bug in it, until you get a minimal test case that shows the bug. Then we can easily see what's going wrong, and whether it's a bug in the program or perhaps (unlikely) a bug with the Pandora compiler or libs or whatever. But if you didn't write the program, you might not want to go to all that trouble.


Where is the actual source code, is it mirall-1.2.1.tar.bz2 , or in git somewhere...?
Yeah, I didn't write the program. Just happened to want to use it on my pandora.

I did note just now when testing that keeping the char declaration in without any code using it doesn't cause a sigsegv. Will have to look more into what triggers exactly.
 
Last edited by a moderator:
Here's the source directory and binaries I was using. Have been using yactfeau. Just put the utmp files in the /mnt/utmp folder and src files in Pandora dir used for yactfeau. There are build directories for the csync library and GUI with txt files with the commands I used to build in them. iniparser should already be compiled and in lib folder so shouldn’t need to rebuild that. You can change the sh file in scripts if you'd like to start a terminal in order to launch gdb.



owncloudsync-utmp.tar.gz
 

Attachments

  • owncloudsync-src.tar.gz
    6.7 MB · Views: 183
  • owncloudsync-utmp.tar.gz
    1.5 MB · Views: 171
Last edited by a moderator:
It doesn't look like there's a problem in the snippet you gave. It might be crashing because you're running out of stack space. That's what a crash on function entry often indicates. Tell us what the value of sp is (by doing info reg in gdb)
 
It doesn't look like there's a problem in the snippet you gave. It might be crashing because you're running out of stack space. That's what a crash on function entry often indicates. Tell us what the value of sp is (by doing info reg in gdb)
This is the line with sp:

Code:
sp   0x43796748   0x43796748
 
That doesn't look like it hit the limit, that looks like it got totally corrupted (or you allocated a really huge temporary array and happened to not actually access it). The only reason the function succeeds if you comment that line out is because it must not use the stack at all.

So the real cause is somewhere else, before this code is ran..
 
That doesn't look like it hit the limit, that looks like it got totally corrupted (or you allocated a really huge temporary array and happened to not actually access it). The only reason the function succeeds if you comment that line out is because it must not use the stack at all.


So the real cause is somewhere else, before this code is ran..
If this is a corrupted stack, what kind of things in the code should I look for that would be causing stack corruption?
 

Attachments

  • memcheck_log_2013.02.26_17:10:54.xml.zip
    20.1 KB · Views: 189
It seems the csync devs think the problem is platform specific. I'll see if I can check if compiling this with the onboard gcc 4.7 changes anything, but not sure where I'd look for a solution from here if that doesn't help.
 
Its a common pattern for something to work on say an x86 desktop, and then not on an ARM device; its easy to then blame the platform, but usually its your code ;) Back 20 years ago the compilers were full of bugs, but these days its better to assume your own code first.

Why this sort of thing? x86 is more forgiving than many (opcodes on even or odd or 4b boundaries etc, no problem), and the desktop builds often are full of padding, or allocations are further apart with lots of space between.. or debugging padding etc. So you can oftem overrun a few bytes here or there and no problem. But then you build on an ARM device, and often a byte here or there will cause major issues.

At a guess to me, it looks like you've corrupted prior to this call; you've clobbered your stack somewhere. Usually its an off--by-one bug, which is pretty hard to avoid every time. Usually its a string you've allocated at 50b and then you've made a 50b strimng and the trailing \0 is out of bounds by 1....

Or you've alloocated a buffer and gotten random junk in there, then strcpy'd it into a known size buffer and obliterated everything if the \0 was too far down in the random garbage, etc.

"efence" type protection can help, but not sure if that works on pandora off the top of my head (ie: allocate in a wasteful fashion, with lots of space in between, and then overruns may cause faults that normally wouldnt' happen if your allocations are all snug up against each other.)

Time to go through your code bit by bit :)
 
Its a common pattern for something to work on say an x86 desktop, and then not on an ARM device; its easy to then blame the platform, but usually its your code ;) Back 20 years ago the compilers were full of bugs, but these days its better to assume your own code first.

Why this sort of thing? x86 is more forgiving than many (opcodes on even or odd or 4b boundaries etc, no problem), and the desktop builds often are full of padding, or allocations are further apart with lots of space between.. or debugging padding etc. So you can oftem overrun a few bytes here or there and no problem. But then you build on an ARM device, and often a byte here or there will cause major issues.

At a guess to me, it looks like you've corrupted prior to this call; you've clobbered your stack somewhere. Usually its an off--by-one bug, which is pretty hard to avoid every time. Usually its a string you've allocated at 50b and then you've made a 50b strimng and the trailing \0 is out of bounds by 1....

Or you've alloocated a buffer and gotten random junk in there, then strcpy'd it into a known size buffer and obliterated everything if the \0 was too far down in the random garbage, etc.

"efence" type protection can help, but not sure if that works on pandora off the top of my head (ie: allocate in a wasteful fashion, with lots of space in between, and then overruns may cause faults that normally wouldnt' happen if your allocations are all snug up against each other.)

Time to go through your code bit by bit :)
I decided to try out efence like you suggested since it seemed simple to test. If what I'm seeing is right, the corruption might be coming from the system Qt libs.#0 0x40027408 in slotForInternalAddress (address=<value optimized out>)
at efence.c:649
count = 8878
#1 free (address=<value optimized out>) at efence.c:720
slot = 0x4bd97290
previousSlot = 0x4bd2f000
nextSlot = 0x4bd6c3d8
#2 0x40bed3fc in ?? () from /usr/lib/libQtCore.so.4
No symbol table info available.
#3 0x40bed3fc in ?? () from /usr/lib/libQtCore.so.4
No symbol table info available.
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
I might try loading my own Qt libs for a test and see if that's an issue.
EDIT:Hm, this is different.

#0 0x400273cc in slotForInternalAddressPreviousTo (
address=<value optimized out>) at efence.c:668
#1 free (address=<value optimized out>) at efence.c:719
#2 0x40e46cb0 in QFSFileEngine::~QFSFileEngine() ()
from /mnt/utmp/owncloudsync/lib/libQtCore.so.4
#3 0x40e02790 in QFileInfo::~QFileInfo() ()
from /mnt/utmp/owncloudsync/lib/libQtCore.so.4
#4 0x40fbf640 in Mirall::Folder::checkLocalPath() ()
from /mnt/utmp/owncloudsync/lib/libowncloudsync.so.0
#5 0x40fc07a0 in Mirall::Folder::Folder(QString const&, QString const&, QString const&, QObject*) ()
from /mnt/utmp/owncloudsync/lib/libowncloudsync.so.0
#6 0x40fd2218 in Mirall::eek:wnCloudFolder::eek:wnCloudFolder(QString const&, QString const&, QString const&, QObject*) ()
from /mnt/utmp/owncloudsync/lib/libowncloudsync.so.0
#7 0x40fbb770 in Mirall::FolderMan::setupFolderFromConfigFile(QString const&) () from /mnt/utmp/owncloudsync/lib/libowncloudsync.so.0
#8 0x40fbc238 in Mirall::FolderMan::setupKnownFolders() ()
from /mnt/utmp/owncloudsync/lib/libowncloudsync.so.0
---Type <return> to continue, or q <return> to quit---
#9 0x0002cec0 in Mirall::Application::Application(int&, char**) ()
#10 0x00025a1c in main ()
Turing on debug symbols for Mirrall gives some missing details:

Code:
#0  0x400273cc in slotForInternalAddressPreviousTo (
    address=<value optimized out>) at efence.c:668
#1  free (address=<value optimized out>) at efence.c:719
#2  0x40d6dc48 in qFree(void*) ()
   from /mnt/utmp/owncloudsync/lib/libQtCore.so.4
#3  0x000626a0 in QList<QString>::free (this=0xbefff25c, 
    __in_chrg=<value optimized out>)
    at /mnt/utmp/owncloudsync/include/QtCore/qlist.h:745
#4  ~QList (this=0xbefff25c, __in_chrg=<value optimized out>)
    at /mnt/utmp/owncloudsync/include/QtCore/qlist.h:717
#5  0x40e4c4f4 in QFileSystemWatcher::addPath(QString const&) ()
   from /mnt/utmp/owncloudsync/lib/libQtCore.so.4
#6  0x40fbf6d0 in Mirall::Folder::checkLocalPath (this=0x48e9cf98)
    at /home/eyecreate/Pandora/owncloudsync/mirall-1.2.1/src/mirall/folder.cpp:112
#7  0x40fc1238 in Folder (this=0x48e9cf98, alias=..., path=..., 
    secondPath=<value optimized out>, parent=0x41002020)
    at /home/eyecreate/Pandora/owncloudsync/mirall-1.2.1/src/mirall/folder.cpp:75
---Type <return> to continue, or q <return> to quit---
#8  0x40fd3434 in ownCloudFolder (this=0x48f153c0, alias=..., path=..., 
    secondPath=..., parent=0x44caefdc)
    at /home/eyecreate/Pandora/owncloudsync/mirall-1.2.1/src/mirall/owncloudfolder.cpp:62
#9  0x40fbbb88 in Mirall::FolderMan::setupFolderFromConfigFile (
    this=0x44caefdc, file=...)
    at /home/eyecreate/Pandora/owncloudsync/mirall-1.2.1/src/mirall/folderman.cpp:278
#10 0x40fbc528 in Mirall::FolderMan::setupKnownFolders (this=0x44caefdc)
    at /home/eyecreate/Pandora/owncloudsync/mirall-1.2.1/src/mirall/folderman.cpp:103
#11 0x0002d4f0 in Application (this=0xbefff5e0, argc=<value optimized out>, 
    argv=<value optimized out>)
    at /home/eyecreate/Pandora/owncloudsync/mirall-1.2.1/src/mirall/application.cpp:164
#12 0x00025adc in main (argc=1, argv=0xbefff7d4)
    at /home/eyecreate/Pandora/owncloudsync/mirall-1.2.1/src/main.cpp:21
 
Last edited by a moderator:
Back
Top