locked
bug in win32 API file creation RE: long filepaths being let in, causes apps to crash RRS feed

  • Question

  • I think the crashes have been caused by some files in some very popular applications which have very long filepaths. they show up worst on XP boxes,which have a very long APPDATA. 

    some file trees in APPDATA are extremely long, and including the username, exceed 260 characters maximum filepath length for a file (MAX_PATH in the C++ compiler).  one file I was looking at was 264 characters.  this has been causing crashes in anything that walks a directory tree which uses char arrays for filepaths.  so this is a security issue.

    Apps this problem can cause to crash or work incorrectly are:

    • backup.
    • disk cloning.
    • file finding/locating (like whereis or file counting for backup or software testing purposes).
    • file tree copying.
    • disc burning.
    • file compression, since it does entire trees (should someone wish to use that on a filepath that long - they might).
    • any code that walks or touches a directory tree.
    • chkdsk.
    • autochk.
    • defrag.
    • virus scanners, malware scanners.
    • anything that touches the affected part of the filesystem could crash.
    • anything that walks the directory tree.
    • in Win32 API, anything file related or directory related regarding creating files, CreateFile(), I think have filepath length leaks, as well as other functions less nicely named like _open(), etc. which are more likely used by installers... I am sure I am missing some.

    I can almost bet that windows vista, 7, 98, 2000, and 8 have this problem as well.

     

    windows XP via its win32 API lets these too-long-filepaths into NTFS, FAT32, and the mac might let that in too into HPFS (an NTFS clone) if their OS API is bad enough... 

    this causes crashes (access violations, error 0xc0000005) in any application that walks a directory tree that is not coded for variable-length filepath/directory  strings.  this means that an attempt was made to access memory that was out-of-bounds for the array.

    a workaround is instead of using

    char sFilePath[MAX_PATH+1];


    to use variable-length
       
    string sFilePath; 


    and whenever you need to grab a C string for Win32 calls, use
       
    sFilePath.c_str()


    that's the easy way of doing it.  don't know about UNICODE yet.

    I have proper source code for walking a directory tree, but it is GPL'd, and I suspect that this will not suit your needs.  the above information is only a workaround for application coders.

     

    the win32 API's filepath encoding

    I have already experienced issues with my antivirus crashing after 2 weeks worth of scan of 2.6TB of data because of a popular app which is causing this.  and I will bet that this was the cause.

    to see if there are such files in your system, in a cmd shell, do

     

    dir/ah /a-h /as /a-s /a-d /s/b \* > files
    
    dir/ah /a-h /as /a-s /ad /s/b \* > dirs

     

    You will need a programmer's editor like The Semware Editor.  it has a macro in utilities->potpourri->longstln with the capability of showing the longest line. Really that's what you are shooting for, you can write a simple C/C++ program to do that too. if you need source code which can do that, I can throw something together in a couple of minutes which is cross-platform.

     

    //longestline.cpp - takes as arguments the filepaths to read and figure out which is the longest line.
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <tr1/stdint.h>
    using namespace std;
    char line[128000+1];
    uint64_t charcountmax=0;
    int main(int argc, char * argv[]) {
    int i;
    string sLine;
    for (i=1; i < argc; i++) {
    charcountmax=0;
    ifstream f;
    f.open(argv[i], ifstream::in);
    if (!f.good()) {
    //skip to next file
    f.close();
    continue;
    }
    while (f.good()) {
    f.getline(line, 128000);
    string sLine=line;
    if (sLine.size() > charcountmax) {
    charcountmax = sLine.size();
    }
    if (!f.good()) {
    //close this file
    break;
    }
    }
    f.close();
    cout<<"\""<<argv[i]<<"\" has "<<charcountmax<<" characters on longest line."<<endl;
    }
    return 0;
    }

     







    Monday, January 9, 2012 12:45 PM