Просмотр исходного кода

apt-pkg/algorithms.cc: Avoid stack buffer overflow in KillList

Dynamically allocate KillList in order to avoid an overflow when
more than 100 elements would be written to it.

This happened while playing around with the status file from
Bug#701069 on a modern system.
Julian Andres Klode лет назад: 10
Родитель
Сommit
f99b06213e
1 измененных файлов с 9 добавлено и 10 удалено
  1. 9 10
      apt-pkg/algorithms.cc

+ 9 - 10
apt-pkg/algorithms.cc

@@ -725,6 +725,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
       changing a breaks c) */
       changing a breaks c) */
    bool Change = true;
    bool Change = true;
    bool const TryFixByInstall = _config->FindB("pkgProblemResolver::FixByInstall", true);
    bool const TryFixByInstall = _config->FindB("pkgProblemResolver::FixByInstall", true);
+   std::vector<PackageKill> KillList;
    for (int Counter = 0; Counter != 10 && Change == true; Counter++)
    for (int Counter = 0; Counter != 10 && Change == true; Counter++)
    {
    {
       Change = false;
       Change = false;
@@ -767,12 +768,12 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
 	    clog << "Investigating (" << Counter << ") " << I << endl;
 	    clog << "Investigating (" << Counter << ") " << I << endl;
 	 
 	 
 	 // Isolate the problem dependency
 	 // Isolate the problem dependency
-	 PackageKill KillList[100];
-	 PackageKill *LEnd = KillList;
 	 bool InOr = false;
 	 bool InOr = false;
 	 pkgCache::DepIterator Start;
 	 pkgCache::DepIterator Start;
 	 pkgCache::DepIterator End;
 	 pkgCache::DepIterator End;
-	 PackageKill *OldEnd = LEnd;
+	 size_t OldSize = 0;
+
+	 KillList.resize(0);
 	 
 	 
 	 enum {OrRemove,OrKeep} OrOp = OrRemove;
 	 enum {OrRemove,OrKeep} OrOp = OrRemove;
 	 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList();
 	 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList();
@@ -782,7 +783,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
 	    if (Start == End)
 	    if (Start == End)
 	    {
 	    {
 	       // Decide what to do
 	       // Decide what to do
-	       if (InOr == true && OldEnd == LEnd)
+	       if (InOr == true && OldSize == KillList.size())
 	       {
 	       {
 		  if (OrOp == OrRemove)
 		  if (OrOp == OrRemove)
 		  {
 		  {
@@ -816,7 +817,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
 		  continue;
 		  continue;
 
 
 	       InOr = Start != End;
 	       InOr = Start != End;
-	       OldEnd = LEnd;
+	       OldSize = KillList.size();
 	    }
 	    }
 	    else
 	    else
             {
             {
@@ -979,10 +980,8 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
 		
 		
 		  if (Debug == true)
 		  if (Debug == true)
 		     clog << "  Added " << Pkg.FullName(false) << " to the remove list" << endl;
 		     clog << "  Added " << Pkg.FullName(false) << " to the remove list" << endl;
-		  
-		  LEnd->Pkg = Pkg;
-		  LEnd->Dep = End;
-		  LEnd++;
+
+		  KillList.push_back({Pkg, End});
 		  
 		  
 		  if (Start.IsNegative() == false)
 		  if (Start.IsNegative() == false)
 		     break;
 		     break;
@@ -1032,7 +1031,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
 	 // Apply the kill list now
 	 // Apply the kill list now
 	 if (Cache[I].InstallVer != 0)
 	 if (Cache[I].InstallVer != 0)
 	 {
 	 {
-	    for (PackageKill *J = KillList; J != LEnd; J++)
+	    for (auto J = KillList.begin(); J != KillList.end(); J++)
 	    {
 	    {
 	       Change = true;
 	       Change = true;
 	       if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0)
 	       if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0)