Bug 90004 - Filedialog crash when saving in directory with long filenames
Summary: Filedialog crash when saving in directory with long filenames
Status: RESOLVED WORKSFORME
Alias: None
Product: kio
Classification: Frameworks and Libraries
Component: kfile (show other bugs)
Version: unspecified
Platform: Compiled Sources Solaris
: NOR crash
Target Milestone: ---
Assignee: Carsten Pfeiffer
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-09-22 11:19 UTC by Nicolas Brisset
Modified: 2007-12-11 20:20 UTC (History)
3 users (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nicolas Brisset 2004-09-22 11:19:56 UTC
Version:            (using KDE KDE 3.3.0)
Installed from:    Compiled From Sources
Compiler:          gcc 3.3.2 
OS:                Solaris

Crashes sometimes happen in all my KDE applications when trying to enter a file name in the file dialog called by the "Save As" menu.
After a long period of painful experiments, I think I have found the reason for this: apparently, whenever there is a file with a long name in the directory I'm trying to save to, it crashes. Experiments suggest the limit to be at 25 characters before the extension (25 still OK, 26 crashes).

I believe this may be related to bug #90001 I have just entered as changing the filename to print to now works (I have renamed all "long" files in my HOME).
It may actually be a long-standing bug since bug #83708 looks a lot like this too. But since it is a bit old, I thought I'd rather open a "fresh" report.
Comment 1 Nicolas Goutte 2004-09-22 11:39:20 UTC
I am not sure that it is bug #83708, as Kate really has a problem.

You seem to use Solaris. Does the filesystem support more than 25 characters? (I am not telling that it is good that it crashes, I am just trying to help to find the reason.)

Have a nice day!
Comment 2 Nicolas Brisset 2004-09-22 11:55:08 UTC
Yes, Solaris supports long filenames (and even large files)! The bug may still happen on Solaris only, I haven't installed KDE 3.3 on my Linux PC yet to check it...
Comment 3 Nicolas Goutte 2004-09-22 12:34:46 UTC
If you have a Qt-only program (like Qt Designer) can you try to save with long 
filenames. (To see if the problem is more in KDE or in Qt.)

Have a nice day!

Comment 4 Nicolas Brisset 2004-09-22 12:48:41 UTC
Saving with Qt Designer works fine even with long/weird names, as it always has. The problem has appeared with the recent switch from KDE 3.2.1 to KDE 3.3.0.
Comment 5 Aaron Williams 2004-11-06 05:02:58 UTC
I can confirm that I am seeing the same problem on my Solaris setup with KDE 3.3.1.  I do not have this problem with kde 3.2.x.  The crash occurs in DirectoryListThread::run()

I have been trying to track this down and can easily reproduce this and get a stack dump.

#0  0xfe05d2f4 in QValueListConstIterator<QString>::operator++ (
    this=0xfc20bc00) at /opt/qt/qt-3.3.3/include/qvaluelist.h:191
191             node = node->next;
(gdb) bt
#0  0xfe05d2f4 in QValueListConstIterator<QString>::operator++ (
    this=0xfc20bc00) at /opt/qt/qt-3.3.3/include/qvaluelist.h:191
#1  0xfe003648 in DirectoryListThread::run (this=0x53d658)
    at kurlcompletion.cpp:209
#2  0xfce32f84 in QThreadInstance::start (_arg=0x4e373c)
    at kernel/qthread_unix.cpp:119
#3  0xfc6eb74c in _thread_start () from /usr/lib/libthread.so.1
#4  0xfc6eb74c in _thread_start () from /usr/lib/libthread.so.1
Previous frame identical to this frame (corrupt stack?)
(gdb) up
#1  0xfe003648 in DirectoryListThread::doRun (this=0x53d658)
    at kurlcompletion.cpp:209
209         for ( QStringList::ConstIterator it = m_dirList.begin();
(gdb) p it
$1 = {node = 0x41343236}
(gdb) down
#0  0xfe05d2f4 in QValueListConstIterator<QString>::operator++ (
    this=0xfc20bc00) at /opt/qt/qt-3.3.3/include/qvaluelist.h:191
191             node = node->next;
(gdb) p node
$2 = (QValueListNode<QString> *) 0x41343236
(gdb) p *node
Cannot access memory at address 0x41343236


Note that my line numbers do not match since I have been trying to track down the problem and added a lot of kdDebug() messages.

I can see filenames getting mangled in QFile::decodeName, i.e.:

kmail: dirEntry name = "tslinux-3-1-mcp750-bsp180-1.tar.bz2.part"
kmail: Decoded file "tslinu" from directory name

My code looks like:

                    kdDebug() << "dirEntry name = \"" << QString(dirEntry->d_name) << "\"" << endl;

                    QString file = QFile::decodeName( dirEntry->d_name );

                    kdDebug() << "Decoded file \"" << file <<"\" from directory name" << endl;


Part of this may be due to a bug in Solaris readdir_r, though.  At one point in my code I had a bug and the compiler said d_name was a char[22].  According to Solaris man page, d_name should be able to support a name up to at least NAME_MAX, or pathconf(_PC_NAME_MAX).  I wrote a test program that prints out the return code from pathconf("/home/aaronw", _PC_NAME_MAX) and it returns 256.

I will try replacing readdir_r with readdir and see if that makes a difference.
Comment 6 Aaron Williams 2004-11-06 05:14:13 UTC
See http://lists.w3.org/Archives/Public/www-lib/2001JanMar/0158.html

This looks like this might be the bug.  I am implementing a patch to see if it solves the problem.

-Aaron
Comment 7 Aaron Williams 2004-11-06 06:34:27 UTC
I can confirm that this is indeed the problem.  The following patch fixes the crashing, apply to kdelibs/kio/kio/kurlcompletion.cpp from version 3.3.1:

diff -u kurlcompletion.cpp.old kurlcompletion.cpp
--- kurlcompletion.cpp.old      2004-06-22 10:36:41.000000000 -0700
+++ kurlcompletion.cpp  2004-11-05 21:33:53.869998000 -0800
@@ -219,10 +219,22 @@

                // Loop through all directory entries

-               struct dirent dirPosition;
+               struct dirent *dirPosition;
                struct dirent *dirEntry = 0;
+                // Note that we need to allocate extra storage space for
+                // dirPosition according to the IRIX man page.  This also
+                // fits for Solaris, where failure to do this causes heap
+                // and/or stack corruption.
+
+                // Get maximum file name size for this directory
+                int max_name_length = pathconf( QFile::encodeName( *it ),
+                                                _PC_NAME_MAX);
+                // Allocate position storage
+                dirPosition = (struct dirent *)malloc(sizeof(dirent) +
+                                                      max_name_length + 1);
                while ( !terminationRequested() &&
-                       ::readdir_r( dir, &dirPosition, &dirEntry ) == 0 && dirEntry )
+                       ::readdir_r( dir, dirPosition, &dirEntry ) == 0 &&
+                        dirEntry )
                {
                        // Skip hidden files if m_noHidden is true

@@ -280,6 +292,9 @@

                ::closedir( dir );
                dir = 0;
+
+                free(dirPosition);
+                dirPosition = 0;
        }

        done();

See http://lists.w3.org/Archives/Public/www-lib/2002OctDec/0057.html for more information.
Comment 8 Aaron Williams 2004-11-06 06:49:20 UTC
Here's what the Solaris man page has to say:

     The storage pointed to by entry will be large enough  for  a
     dirent  with  an  array  of char d_name member containing at
     least NAME_MAX (that is,  pathconf(_PC_NAME_MAX))  plus  one
     elements. _PC_NAME_MAX is defined in  <unistd.h>.
Comment 9 Stephan Kulow 2004-11-06 11:30:25 UTC
The patch of Stefan Teleman doesn't work? 
http://lists.kde.org/?l=kde-core-devel&m=109893526806858&w=2
Comment 10 Aaron Williams 2004-12-09 01:19:40 UTC
I don't see this patch in the 3.3.2 release and it looks like it wasn't committed back into the CVS tree.  Could this patch please be checked in?  In the meantime, I am reapplying my patch from 3.3.1 to 3.3.2.
Comment 11 Nicolas Brisset 2005-01-05 15:19:17 UTC
I have just read the last CVS digest and it seems to me that bug #95830 is the same as that one. I will close this and reopen it later in case it's still a problem. If any of you sees a good reason to favor the above fix to that proposed for 95830, get in tough with Michael Pyne.
Comment 12 Michael Pyne 2005-01-05 23:34:40 UTC
Just as a note, this area isn't my department of expertise, I happened to notice a different Solaris user tracking down this bug in the kde-devel mailing list, and since the solution was simple, decided to tackle it.

The threaded URL completion code is by Scott Wheeler, and I'm not sure who handles KFileDialog, except to say that it isn't me. ;)
Comment 13 Aaron Williams 2005-01-06 00:02:53 UTC
I wrote one simple patch that works for Solaris after I tracked down the 
source of the bug..  I had to apply it to 3.3.2 as well.

Basically I added the code to allocate the appropriate space for 
dirPosition and later free it.

i.e.

                // Get maximum file name size for this directory
                int max_name_length = pathconf( QFile::encodeName( *it ),
                                                _PC_NAME_MAX);
                // Allocate position storage
                dirPosition = (struct dirent *)malloc(sizeof(dirent) +
                                                      max_name_length + 1);
        while ( !terminationRequested() &&
                ::readdir_r( dir, dirPosition, &dirEntry ) == 0 &&
                        dirEntry )
        {
...
         }

         free(dirPosition);
         dirPosition=0;