0026345: Shape Healer application crashes trying to run Shape Processing
authoranv <anv@opencascade.com>
Tue, 16 Jun 2015 09:27:09 +0000 (12:27 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 25 Jun 2015 10:02:07 +0000 (13:02 +0300)
Empty element, that was added to the Array, causes an exception while accessing myUserMap

LoadResourceManager is receives environment variable name, but stat is waiting for full path

src/Resource/Resource_Manager.cdl
src/Resource/Resource_Manager.cxx
src/ShapeProcess/ShapeProcess_Context.cxx

index 181c1bc..223d324 100644 (file)
@@ -180,12 +180,21 @@ is
      --          If the resource does not exist, it is created.
      ---Level: Public
 
+     GetResourcePath(myclass;
+                     aPath: in out AsciiString from TCollection;
+                     aName: CString from Standard;
+                     isUserDefaults: Boolean from Standard);
+     ---Purpose: Gets the resource file full path by its name.
+     --          If corresponding environment variable is not set
+     --          or file doesn't exist returns empty string.
+     ---Level: Public
+
+
 ---Category: Private methods.
 
      Load (me: mutable ;
-          aDirectory: in out AsciiString from TCollection;
-           aName:      in out AsciiString from TCollection;
-          aMap:       in out DataMapOfAsciiStringAsciiString)
+           aPath: in out AsciiString from TCollection;
+           aMap:  in out DataMapOfAsciiStringAsciiString)
      is static private;
      ---Level: Internal
 
index 8a98296..d7142e4 100644 (file)
@@ -33,8 +33,7 @@
 #define END      0
 #define EMPTY    1
 #define COMMENT  2
-#define INCLUDE  3
-#define RESOURCE 4
+#define RESOURCE 3
 #define ERROR   -1
 
 static Standard_Integer WhatKindOfLine(OSD_File& aFile,
@@ -51,14 +50,24 @@ Resource_Manager::Resource_Manager(const Standard_CString aName,
                                   const Standard_Boolean Verbose) : myName(aName), myVerbose(Verbose)
 {
   if ( !aDefaultsDirectory.IsEmpty() ) {
-    Load(aDefaultsDirectory,myName,myRefMap);
+    OSD_Path anOSDPath(aDefaultsDirectory);
+    anOSDPath.DownTrek(anOSDPath.Name());
+    anOSDPath.SetName(aName);
+    TCollection_AsciiString aPath;
+    anOSDPath.SystemName(aPath);
+    Load(aPath,myRefMap);
   }
   else
     if (myVerbose)
       cout << "Resource Manager Warning: aDefaultsDirectory is empty." << endl;
 
   if ( !anUserDefaultsDirectory.IsEmpty() ) {
-    Load(anUserDefaultsDirectory,myName,myRefMap);
+    OSD_Path anOSDPath(anUserDefaultsDirectory);
+    anOSDPath.DownTrek(anOSDPath.Name());
+    anOSDPath.SetName(aName);
+    TCollection_AsciiString aPath;
+    anOSDPath.SystemName(aPath);
+    Load(aPath,myRefMap);
   }
   else
     if (myVerbose)
@@ -70,44 +79,34 @@ Resource_Manager::Resource_Manager(const Standard_CString aName,
 {
   Debug = (getenv("ResourceDebug") != NULL) ;
 
-  TCollection_AsciiString EnvVar, CSF_ = "CSF_" ;
   TCollection_AsciiString Directory ;
-  Standard_CString dir ;
 
   if ( getenv ("CSF_ResourceVerbose") != NULL )
     myVerbose = Standard_True;
 
-  EnvVar = CSF_ + aName + "Defaults" ;
-  if ((dir = getenv (EnvVar.ToCString())) != NULL) {
-    Directory = dir;
-    Load(Directory,myName,myRefMap);
-  }
-  else
-    if (myVerbose)
-      cout << "Resource Manager Warning: Environment variable \"" << EnvVar
-          << "\" not set." << endl;
+  TCollection_AsciiString aPath,aUserPath;
+  GetResourcePath(aPath,aName,Standard_False);
+  GetResourcePath(aUserPath,aName,Standard_True);
 
-  EnvVar = CSF_ + aName + "UserDefaults" ;
-  if ((dir = getenv (EnvVar.ToCString())) != NULL) {
-    Directory = dir;
-    Load(Directory, myName, myUserMap);
-  }
-  else
-    if (myVerbose)
-      cout << "Resource Manager Warning: Environment variable \"" << EnvVar
-          << "\" not set." << endl;
+  if (!aPath.IsEmpty())
+    Load(aPath,myRefMap);
+  else if (myVerbose)
+    cout << "Resource Manager Warning: Environment variable \"CSF_" << aName << "Defaults\" not set." << endl;
+
+  if (!aUserPath.IsEmpty())
+    Load(aUserPath,myRefMap);
+  else if (myVerbose)
+    cout << "Resource Manager Warning: Environment variable \"CSF_" << aName << "UserDefaults\" not set." << endl;
 }
 
-void Resource_Manager::Load(TCollection_AsciiString& aDirectory,
-                           TCollection_AsciiString& aName,
-                           Resource_DataMapOfAsciiStringAsciiString& aMap)
+void Resource_Manager::Load(TCollection_AsciiString& aPath,
+                            Resource_DataMapOfAsciiStringAsciiString& aMap)
 {
-  Standard_Integer Kind, Pos;
+  Standard_Integer Kind;
   TCollection_AsciiString Token1, Token2;
   TCollection_AsciiString Directory, Name;
   TCollection_AsciiString FileName;
-  FileName =  aDirectory + "/" + aName;
-  OSD_File File = OSD_Path(FileName);
+  OSD_File File = OSD_Path(aPath);
   File.Open(OSD_ReadOnly,OSD_Protection());
   if (File.Failed()) {
     if (myVerbose)
@@ -121,15 +120,6 @@ void Resource_Manager::Load(TCollection_AsciiString& aDirectory,
     case COMMENT :
     case EMPTY :
       break ;
-    case INCLUDE :
-      Directory = OSD_Path::AbsolutePath(aDirectory,Token1);
-      Pos = Directory.SearchFromEnd("/");
-      if (Pos != 0) {
-       Name = Directory.Split(Pos);
-       Directory.Trunc(Pos-1);
-       Load(Directory,Name,aMap);
-      }
-      break;
     case RESOURCE :
       if (!aMap.Bind(Token1,Token2))
         aMap(Token1) = Token2;
@@ -162,15 +152,6 @@ static Standard_Integer WhatKindOfLine(OSD_File& aFile,
   if (Line.Value(1) == '!')
     return COMMENT;
 
-  if (Line.Value(1) == '#') {
-    Line.Remove(1);
-    if ((Line.Token(" \t")).IsDifferent("include"))
-      return ERROR;
-
-    aToken1 = Line.Token(" \t\n",2);
-    return INCLUDE;
-  }
-
   Pos1 = Line.FirstLocationNotInSet(WhiteSpace, 1, Line.Length());
   if (Line.Value(Pos1) == '\n')
     return EMPTY;
@@ -236,43 +217,46 @@ static Standard_Integer GetLine(OSD_File& aFile,TCollection_AsciiString& aLine)
 //=======================================================================
 Standard_Boolean Resource_Manager::Save() const
 {
-  Standard_Integer Index;
-  TCollection_AsciiString EnvVar, CSF_ = "CSF_";
-  Standard_CString dir;
-
-  EnvVar = CSF_ + myName + "UserDefaults";
+  TCollection_AsciiString anEnvVar("CSF_");
+  anEnvVar += myName;
+  anEnvVar += "UserDefaults";
 
-  if ((dir = getenv (EnvVar.ToCString())) == NULL) {
+  Standard_CString dir;
+  if ((dir = getenv (anEnvVar.ToCString())) == NULL) {
     if (myVerbose)
       cout << "Resource Manager Warning: environment variable \""
-          << EnvVar << "\" not set.  Cannot save resources." << endl ;
+          << anEnvVar << "\" not set.  Cannot save resources." << endl ;
     return Standard_False;
   }
-  TCollection_AsciiString FilePath = dir;
-  OSD_Directory Dir = OSD_Path(FilePath);
+
+  TCollection_AsciiString aFilePath(dir);
+  OSD_Path anOSDPath(aFilePath);
+  OSD_Directory Dir = anOSDPath;
   Standard_Boolean Status = Standard_True;
   if ( !Dir.Exists() ) {
     {
       try {
         OCC_CATCH_SIGNALS
-       Dir.Build(OSD_Protection(OSD_RX, OSD_RWX, OSD_RX, OSD_RX));
+        Dir.Build(OSD_Protection(OSD_RX, OSD_RWX, OSD_RX, OSD_RX));
       }
       catch (Standard_Failure) {
-       Status = Standard_False;
+        Status = Standard_False;
       }
     }
     Status = Status && !Dir.Failed();
     if (!Status) {
       if (myVerbose)
-       cout << "Resource Manager: Error opening or creating directory \"" << FilePath
-            << "\". Permission denied. Cannot save resources." << endl;
+        cout << "Resource Manager: Error opening or creating directory \"" << aFilePath
+             << "\". Permission denied. Cannot save resources." << endl;
       return Standard_False;
     }
   }
 
-  FilePath += "/"; FilePath += myName;
-  OSD_Path Path(FilePath);
-  OSD_File File = Path;
+  anOSDPath.DownTrek(anOSDPath.Name());
+  anOSDPath.SetName(myName);
+  anOSDPath.SystemName(aFilePath);
+
+  OSD_File File = anOSDPath;
   OSD_Protection theProt;
   Status = Standard_True;
   {
@@ -287,41 +271,45 @@ Standard_Boolean Resource_Manager::Save() const
   Status = Status && !File.Failed();
   if (!Status) {
     if (myVerbose)
-      cout << "Resource Manager: Error opening or creating file \"" << FilePath
+      cout << "Resource Manager: Error opening or creating file \"" << aFilePath
            << "\". Permission denied. Cannot save resources." << endl;
     return Standard_False;
   }
 
-  Resource_LexicalCompare Comp;
-  Standard_Integer NbKey = myUserMap.Extent();
-  TColStd_Array1OfAsciiString KeyArray(1,NbKey+1); // 1 more item is added to allow saving empty resource
-  Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString Iter(myUserMap);
-
-  for ( Index = 1; Iter.More(); Iter.Next())
-    KeyArray(Index++)= Iter.Key();
-
-  Resource_QuickSortOfArray1::Sort(KeyArray, Comp);
-
-  TCollection_AsciiString Line, Value;
-  for (Index = 1 ; Index <= NbKey ; Index++) {
-    Value = myUserMap(KeyArray(Index));
-    if (!Value.IsEmpty())
-      switch(Value.Value(1)) {
-      case '\\' :
-      case ' ' :
-      case '\t' :
-       Value.Insert(1,'\\');
-       break;
-      }
-    Line = KeyArray(Index) + ":\t" + Value + "\n";
-
-    if (Debug)
-      cout << "Line = '" << Line << "'" << endl;
-
-    File.Write(Line, Line.Length());
+  const Standard_Integer NbKey = myUserMap.Extent();
+  if (NbKey)
+  {
+    TColStd_Array1OfAsciiString KeyArray(1,NbKey);
+    Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString Iter(myUserMap);
+
+    Standard_Integer Index;
+    for ( Index = 1; Iter.More(); Iter.Next())
+      KeyArray(Index++)= Iter.Key();
+
+    Resource_LexicalCompare Comp;
+    Resource_QuickSortOfArray1::Sort(KeyArray, Comp);
+
+    TCollection_AsciiString Line, Value;
+    for (Index = 1 ; Index <= NbKey ; Index++) {
+      Value = myUserMap(KeyArray(Index));
+      if (!Value.IsEmpty())
+        switch(Value.Value(1)) {
+        case '\\' :
+        case ' ' :
+        case '\t' :
+          Value.Insert(1,'\\');
+          break;
+        }
+      Line = KeyArray(Index) + ":\t" + Value + "\n";
+
+      if (Debug)
+        cout << "Line = '" << Line << "'" << endl;
+
+      File.Write(Line, Line.Length());
+    }
+    if (myVerbose)
+      cout << "Resource Manager: Resources saved in file " << aFilePath << endl;
   }
-  if (myVerbose)
-    cout << "Resource Manager: Resources saved in file " << FilePath << endl;
   File.Close();
   return Standard_True;
 }
@@ -468,3 +456,29 @@ Standard_Boolean Resource_Manager::Find(const Standard_CString aResource) const
     return Standard_True;
   return Standard_False;
 }
+
+//=======================================================================
+//function : GetResourcePath
+//purpose  : 
+//=======================================================================
+
+void Resource_Manager::GetResourcePath (TCollection_AsciiString& aPath, const Standard_CString aName, const Standard_Boolean isUserDefaults)
+{
+  aPath.Clear();
+
+  TCollection_AsciiString anEnvVar("CSF_");
+  anEnvVar += aName;
+  anEnvVar += isUserDefaults?"UserDefaults":"Defaults";
+
+  Standard_CString dir;
+  if ((dir = getenv (anEnvVar.ToCString())) == NULL)
+    return;
+
+  TCollection_AsciiString aResPath(dir);
+
+  OSD_Path anOSDPath(aResPath);
+  anOSDPath.DownTrek(anOSDPath.Name());
+  anOSDPath.SetName(aName);
+
+  anOSDPath.SystemName(aPath);
+}
\ No newline at end of file
index 4dd1a18..8bb62d5 100644 (file)
@@ -67,28 +67,61 @@ Standard_Boolean ShapeProcess_Context::Init (const Standard_CString file,
 //purpose  : 
 //=======================================================================
 
-Handle(Resource_Manager) ShapeProcess_Context::LoadResourceManager (const Standard_CString file)
+Handle(Resource_Manager) ShapeProcess_Context::LoadResourceManager (const Standard_CString name)
 {
   // Optimisation of loading resource file: file is load only once
   // and reloaded only if file date has changed
   static Handle(Resource_Manager) sRC;
-  static Standard_Time mtime;
-  static TCollection_AsciiString name;
-  if ( ! sRC.IsNull() && ! name.IsEqual ( file ) ) sRC.Nullify();
-  if ( ! sRC.IsNull() ) {
-    struct stat buf;
-    if ( ! stat ( file, &buf ) && (Standard_Time)buf.st_mtime != mtime ) {
-      sRC.Nullify();
-      mtime = buf.st_mtime;
+  static Standard_Time sMtime, sUMtime;
+  static TCollection_AsciiString sName;
+
+  struct stat buf;
+  Standard_Time aMtime(0), aUMtime(0);
+  TCollection_AsciiString aPath,aUserPath;
+  Resource_Manager::GetResourcePath(aPath,name,Standard_False);
+  Resource_Manager::GetResourcePath(aUserPath,name,Standard_True);
+  if ( !aPath.IsEmpty() )
+  {
+    stat( aPath.ToCString(), &buf );
+    aMtime = (Standard_Time)buf.st_mtime;
+  }
+  if ( !aUserPath.IsEmpty() )
+  {
+    stat( aUserPath.ToCString(), &buf );
+    aUMtime = (Standard_Time)buf.st_mtime;
+  }
+
+  Standard_Boolean isFileModified = Standard_False;
+  if ( !sRC.IsNull() ) {
+    if ( sName.IsEqual ( name ) ) {
+      if ( sMtime != aMtime )
+      {
+        sMtime = aMtime;
+        isFileModified = Standard_True;
+      }
+      if ( sUMtime != aUMtime )
+      {
+        sUMtime = aUMtime;
+        isFileModified = Standard_True;
+      }
+      if (isFileModified)
+        sRC.Nullify();
     }
+    else
+      sRC.Nullify();
   }
   if ( sRC.IsNull() ) {
 #ifdef OCCT_DEBUG
     cout << "Info: ShapeProcess_Context: Reload Resource_Manager: " 
-         << name.ToCString() << " -> " << file << endl;
+         << sName.ToCString() << " -> " << name << endl;
 #endif
-    sRC = new Resource_Manager ( file );
-    name = file;
+    sRC = new Resource_Manager ( name );
+    if (!isFileModified)
+    {
+      sName = name;
+      sMtime = aMtime;
+      sUMtime = aUMtime;
+    }
   }
   return sRC;
 }
@@ -401,5 +434,4 @@ void ShapeProcess_Context::SetTraceLevel (const Standard_Integer tracelev)
 Standard_Integer ShapeProcess_Context::TraceLevel () const
 {
   return myTraceLev;
-}
-
+}
\ No newline at end of file