View Issue Details

IDProjectCategoryView StatusLast Update
0000380Far ManagerCopy/Movepublic2007-12-01 10:54
Reporteralexmitin Assigned Toalexy  
PrioritynormalSeveritymajorReproducibilityalways
Status closedResolutionfixed 
Fixed in Version1.80 alpha 1 
Summary0000380: Memory leak in ConvertWildcards()
DescriptionFile: strmix.cpp
Line: 234
Function: ConvertWildcards()
Context:

int ConvertWildcards(const wchar_t *SrcName,string &strDest, int SelectedFolderNameLength)
{
...
    wchar_t *Src = _wcsdup (SrcName);
...
}

Problem:
-----------
The pointer "Src" is never freed.


Call stack:
-----------
*1 Far.exe!ConvertWildcards(const wchar_t * SrcName=0x00afc0e0, UnicodeString & strDest={...}, int SelectedFolderNameLength=0)
 2 Far.exe!ShellCopy::ShellCopyOneFile(const wchar_t * Src=0x00afc0e0, const FAR_FIND_DATA_EX & SrcData={...}, const wchar_t * Dest=0x00ae9cf0, int KeepPathPos=0, int Rename=0)
 3 Far.exe!ShellCopy::CopyFileTree(const wchar_t * Dest=0x00ae9cf0)
 4 Far.exe!ShellCopy::ShellCopy(Panel * SrcPanel=0x00aebc68, int Move=0, int Link=0, int CurrentOnly=0, int Ask=1, int & ToPlugin=0, const wchar_t * PluginDestPath=0x00000000)
 5 Far.exe!FileList::ProcessCopyKeys(int Key=65652)
 6 Far.exe!FileList::ProcessKey(int Key=65652)
 7 Far.exe!FilePanels::ProcessKey(int Key=65652)
 8 Far.exe!Manager::ProcessKey(unsigned long Key=65652)
 9 Far.exe!Manager::ProcessMainLoop()
 10 Far.exe!Manager::EnterMainLoop()
 11 Far.exe!MainProcess(const wchar_t * lpwszEditName=0x009f48f0, const wchar_t * lpwszViewName=0x009f49a8, const wchar_t * lpwszDestName1=0x009f4a60, const wchar_t * lpwszDestName2=0x009f4b18, int StartLine=-1, int StartChar=-1, int RegOpt=0)
 12 Far.exe!wmain(int Argc=1, wchar_t * * Argv=0x009f54f0)
 13 Far.exe!__tmainCRTStartup()
 14 Far.exe!wmainCRTStartup()


To reproduce follow these steps:
1) Run the FAR under debugger
2) Put a breakpoint on the following line in the ConvertWildcards() function:

    wchar_t *Src = _wcsdup (SrcName);

3) Copy any file using F5 in FAR Manager.
4) After the breakpoint hit step through the code.
Additional InformationFAR 1.80 alpha 1 build 359
TagsNo tags attached.
Build368

Activities

Tonal

2007-11-27 14:00

reporter   bugnote:0000879

Проще всего решается так:
[diff]
Index: strmix.cpp
===================================================================
--- strmix.cpp (revision 1323)
+++ strmix.cpp (working copy)
@@ -231,7 +231,8 @@
 
     wchar_t *PartAfterFolderName; //BUGBUG string
     wchar_t *PartBeforeName; //BUGBUG string
- wchar_t *Src = _wcsdup (SrcName);
+ string SrcTmp(SrcName);
+ wchar_t *Src = SrcTmp.GetBuffer();
   //char PartBeforeName[NM],PartAfterFolderName[NM];
 
     DestNamePtr = strDest.GetBuffer ((int)(strDest.GetLength()+StrLength(SrcName)+1)); //???
[/diff]

Tonal

2007-12-01 07:06

reporter   bugnote:0000893

Нашел ещё один лик в этой же функции: PartAfterFolderName тоже нигде не удаляется.
Подумал, что реализация на строках в этой ситуации расточительна, поэтому
предлагаю диф решения этих проблем на гвардах, и файл с реализацией гвардов (ScopedGuards.hpp).
[diff]
Index: strmix.cpp
===================================================================
--- strmix.cpp (revision 1335)
+++ strmix.cpp (working copy)
@@ -38,6 +38,7 @@
 #include "fn.hpp"
 #include "plugin.hpp"
 #include "lang.hpp"
+#include "ScopedGuards.hpp"
 
 string &InsertCommas(unsigned __int64 li,string &strDest)
 {
@@ -229,9 +230,9 @@
     wchar_t *DestNamePtr, *SrcNamePtr;
     const wchar_t *CurWildPtr;
 
- wchar_t *PartAfterFolderName; //BUGBUG string
+ ScoredWDup PartAfterFolderName; //BUGBUG string
     wchar_t *PartBeforeName; //BUGBUG string
- wchar_t *Src = _wcsdup (SrcName);
+ ScoredWDup Src(_wcsdup (SrcName));
   //char PartBeforeName[NM],PartAfterFolderName[NM];
 
     DestNamePtr = strDest.GetBuffer ((int)(strDest.GetLength()+StrLength(SrcName)+1)); //???
@@ -247,7 +248,7 @@
 
     if (SelectedFolderNameLength!=0)
     {
- PartAfterFolderName = _wcsdup (Src+SelectedFolderNameLength);
+ PartAfterFolderName.reset(_wcsdup (Src+SelectedFolderNameLength));
         Src[SelectedFolderNameLength]=0;
     }
 
@@ -615,7 +616,7 @@
 string &RemoveChar(string &strStr,wchar_t Target,BOOL Dup)
 {
   wchar_t *Ptr = strStr.GetBuffer ();
- wchar_t *Str = Ptr, *StrBegin = Ptr, Chr;
+ wchar_t *Str = Ptr, Chr;
   while((Chr=*Str++) != 0)
   {
     if(Chr == Target)
[/diff]

2007-12-01 07:06

 

ScopedGuards.hpp (2,716 bytes)   
#ifndef __SCOPEDGUARD_HPP__
#define __SCOPEDGUARD_HPP__
/*
ScopedGuards.hpp
*/
/*
Copyright (c) 1996 Eugene Roshal
Copyright (c) 2000 Far Group
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. The name of the authors may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

template <class T, class Traits> 
struct ScoredBase {
  ScoredBase(): elt(0) {}
  explicit ScoredBase(T *elt): elt(elt) {}
  ~ScoredBase() {Traits::dispose(elt);}
  const T *get() const {return elt;}
  T *get() {return elt;}
  operator const T *() const {return get();}
  operator T *() {return get();}

  void swap(ScoredBase<T, Traits>& other) {
    T *tmp = elt;
    elt = other.elt;
    other.elt = tmp;
  }
  void reset(T *newElt) {
    if (elt == newElt)
      return;
    ScoredBase<T, Traits> other(newElt);
    swap(other);
  }
  T * release() {
    T *tmp = elt;
    elt = 0;
    return tmp;
  }
  private:
    T *elt;
    ScoredBase(const ScoredBase&);
    ScoredBase& operator=(const ScoredBase&);
};

template <class T>
struct NewTraits {
  static void dispose(T *elt) {delete elt;}
};

template <class T>
struct ScopedGuard : ScoredBase<T, NewTraits<T> > {
  ScopedGuard(T *elt): ScoredBase<T, NewTraits<T> >(elt) {}
};

void  __cdecl xf_free(void *);
struct FreeTraits {
  static void dispose(void *elt) {xf_free(elt);}
};

typedef ScoredBase<wchar_t, FreeTraits> ScoredWDup;

#endif //__SCOPEDGUARD_HPP__


ScopedGuards.hpp (2,716 bytes)   

alexy

2007-12-01 10:54

administrator   bugnote:0000896

368

Issue History

Date Modified Username Field Change
2007-11-25 23:29 alexmitin New Issue
2007-11-27 14:00 Tonal Note Added: 0000879
2007-12-01 07:06 Tonal Note Added: 0000893
2007-12-01 07:06 Tonal File Added: ScopedGuards.hpp
2007-12-01 07:28 alexy Project Known Error => Far Manager
2007-12-01 07:32 alexy Status new => assigned
2007-12-01 07:32 alexy Assigned To => alexy
2007-12-01 10:54 alexy Build => 368
2007-12-01 10:54 alexy Status assigned => closed
2007-12-01 10:54 alexy Note Added: 0000896
2007-12-01 10:54 alexy Resolution open => fixed
2007-12-01 10:54 alexy Fixed in Version => 1.80 alpha 1