ALT Linux Team development discussions
 help / color / mirror / Atom feed
* [devel] [PATCH for apt 1/2] Add option for debugging DynamicMMap::Allocate
@ 2019-12-06 13:16 Aleksei Nikiforov
  2019-12-06 13:16 ` [devel] [PATCH for apt 2/2] Fix pointer arithmetics Aleksei Nikiforov
  2019-12-08 22:50 ` [devel] [PATCH for apt 1/2] Add option for debugging DynamicMMap::Allocate Dmitry V. Levin
  0 siblings, 2 replies; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-06 13:16 UTC (permalink / raw)
  To: devel; +Cc: Aleksei Nikiforov

---
 apt/apt-pkg/contrib/mmap.cc | 15 +++++++++++++++
 apt/doc/apt.conf.5.sgml     |  2 +-
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
index a3b06cc..cf01be9 100644
--- a/apt/apt-pkg/contrib/mmap.cc
+++ b/apt/apt-pkg/contrib/mmap.cc
@@ -265,6 +265,21 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
    // No pool is allocated, use an unallocated one
    if (I == Pools + PoolCount)
    {
+      static const bool debug_grow = _config->FindB("Debug::DynamicMMap::Allocate", false);
+
+      if (debug_grow)
+      {
+         Pool *pool_iter = Pools;
+         size_t pool_idx = 0;
+
+         _error->Warning(_("DynamicMMap::Allocate: allocating item of size %lu"), ItemSize);
+
+         for (; pool_idx < PoolCount; ++pool_iter, ++pool_idx)
+         {
+            _error->Warning(_("DynamicMMap::Allocate: Pool %zu, item size: %lu, start: %lu, count: %lu"), pool_idx, pool_iter->ItemSize, pool_iter->Start, pool_iter->Count);
+         }
+      }
+
       // Woops, we ran out, the calling code should allocate more.
       if (Empty == 0)
       {
diff --git a/apt/doc/apt.conf.5.sgml b/apt/doc/apt.conf.5.sgml
index 0a72e45..72fc0c3 100644
--- a/apt/doc/apt.conf.5.sgml
+++ b/apt/doc/apt.conf.5.sgml
@@ -526,7 +526,7 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
    disable the inclusion of statfs data in CDROM IDs.
    </para><para>
    To debug issues related to dynamic memory allocation, an option
-   <literal/Debug::DynamicMMap::Grow/ may be used.
+   <literal/Debug::DynamicMMap::Grow/ and <literal/Debug::DynamicMMap::Allocate/ may be used.
    </para>
  </RefSect1>
  
-- 
2.24.0



^ permalink raw reply	[flat|nested] 34+ messages in thread

* [devel] [PATCH for apt 2/2] Fix pointer arithmetics
  2019-12-06 13:16 [devel] [PATCH for apt 1/2] Add option for debugging DynamicMMap::Allocate Aleksei Nikiforov
@ 2019-12-06 13:16 ` Aleksei Nikiforov
  2019-12-06 13:36   ` Ivan A. Melnikov
                     ` (2 more replies)
  2019-12-08 22:50 ` [devel] [PATCH for apt 1/2] Add option for debugging DynamicMMap::Allocate Dmitry V. Levin
  1 sibling, 3 replies; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-06 13:16 UTC (permalink / raw)
  To: devel; +Cc: Aleksei Nikiforov

This change should fix pointer arithmetic issues for e2k.
---
 apt/apt-pkg/Makefile.am          |  1 +
 apt/apt-pkg/cacheiterators.h     | 14 ++++++++------
 apt/apt-pkg/contrib/mmap.cc      |  8 +++++---
 apt/apt-pkg/pkgcachegen.cc       | 15 ++++++++-------
 apt/apt-pkg/rebase_pointer.h     | 16 ++++++++++++++++
 apt/apt-pkg/rpm/rpmlistparser.cc |  3 ++-
 6 files changed, 40 insertions(+), 17 deletions(-)
 create mode 100644 apt/apt-pkg/rebase_pointer.h

diff --git a/apt/apt-pkg/Makefile.am b/apt/apt-pkg/Makefile.am
index 4c0d234..d038d01 100644
--- a/apt/apt-pkg/Makefile.am
+++ b/apt/apt-pkg/Makefile.am
@@ -94,6 +94,7 @@ libapt_pkg_la_SOURCES = \
 	pkgsystem.h \
 	policy.cc \
 	policy.h \
+	rebase_pointer.h \
 	repository.cc \
 	repository.h \
 	scopeexit.h \
diff --git a/apt/apt-pkg/cacheiterators.h b/apt/apt-pkg/cacheiterators.h
index a4bf670..51f70c1 100644
--- a/apt/apt-pkg/cacheiterators.h
+++ b/apt/apt-pkg/cacheiterators.h
@@ -34,6 +34,8 @@
 #pragma interface "apt-pkg/cacheiterators.h"
 #endif 
 
+#include <apt-pkg/rebase_pointer.h>
+
 #include <set>
 
 // Package Iterator
@@ -89,7 +91,7 @@ class pkgCache::PkgIterator
    {
       if (Owner == 0 || Pkg == 0)
          return;
-      Pkg += static_cast<Package const *>(newMap) - static_cast<Package const *>(oldMap);
+      Pkg = RebasePointer(Pkg, oldMap, newMap);
    }
 
    // Constructors
@@ -151,7 +153,7 @@ class pkgCache::VerIterator
    {
       if (Owner == 0 || Ver == 0)
          return;
-      Ver += static_cast<Version const *>(newMap) - static_cast<Version const *>(oldMap);
+      Ver = RebasePointer(Ver, oldMap, newMap);
    }
 
    inline VerIterator() : Ver(0), Owner(0) {};   
@@ -224,7 +226,7 @@ class pkgCache::DepIterator
    {
       if (Owner == 0 || Dep == 0)
          return;
-      Dep += static_cast<Dependency const *>(newMap) - static_cast<Dependency const *>(oldMap);
+      Dep = RebasePointer(Dep, oldMap, newMap);
    }
 
    inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) :
@@ -283,7 +285,7 @@ class pkgCache::PrvIterator
    {
       if (Owner == 0 || Prv == 0)
          return;
-      Prv += static_cast<Provides const *>(newMap) - static_cast<Provides const *>(oldMap);
+      Prv = RebasePointer(Prv, oldMap, newMap);
    }
 
    inline PrvIterator() : Prv(0), Type(PrvVer), Owner(0)  {};
@@ -346,7 +348,7 @@ class pkgCache::PkgFileIterator
    {
       if (Owner == 0 || File == 0)
          return;
-      File += static_cast<PackageFile const *>(newMap) - static_cast<PackageFile const *>(oldMap);
+      File = RebasePointer(File, oldMap, newMap);
    }
 
    // Constructors
@@ -387,7 +389,7 @@ class pkgCache::VerFileIterator
    {
       if (Owner == 0 || FileP == 0)
          return;
-      FileP += static_cast<VerFile const *>(newMap) - static_cast<VerFile const *>(oldMap);
+      FileP = RebasePointer(FileP, oldMap, newMap);
    }
 
    inline VerFileIterator() : Owner(0), FileP(0) {};
diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
index cf01be9..ddae2ff 100644
--- a/apt/apt-pkg/contrib/mmap.cc
+++ b/apt/apt-pkg/contrib/mmap.cc
@@ -30,6 +30,7 @@
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/mmap.h>
 #include <apt-pkg/error.h>
+#include <apt-pkg/rebase_pointer.h>
 
 #include <apti18n.h>
 
@@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
       Pool* oldPools = Pools;
       auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
       if (Pools != oldPools)
-         I += Pools - oldPools;
+         I = RebasePointer(I, oldPools, Pools);
 
       // Does the allocation failed ?
       if (!idxResult)
@@ -371,7 +372,7 @@ bool DynamicMMap::Grow(unsigned long long size)
       Fd->Write(&C,sizeof(C));
    }
 
-   unsigned long const poolOffset = Pools - ((Pool*) Base);
+   const void * const old_base = Base;
 
    if (Fd != 0)
    {
@@ -408,7 +409,8 @@ bool DynamicMMap::Grow(unsigned long long size)
       memset((char*)Base + WorkSpace, 0, newSize - WorkSpace);
    }
 
-   Pools = (Pool*) Base + poolOffset;
+   if (Base != old_base)
+      Pools = RebasePointer(Pools, old_base, Base);
    WorkSpace = newSize;
 
    return true;
diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc
index 654c81c..10a0fd7 100644
--- a/apt/apt-pkg/pkgcachegen.cc
+++ b/apt/apt-pkg/pkgcachegen.cc
@@ -26,6 +26,7 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/rebase_pointer.h>
 
 #include <apti18n.h>
 
@@ -116,11 +117,11 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
 
    Cache.ReMap(false);
 
-   CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap;
+   CurrentFile = RebasePointer(CurrentFile, oldMap, newMap);
 
    for (size_t i = 0; i < _count(UniqHash); ++i)
       if (UniqHash[i] != 0)
-         UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap;
+         UniqHash[i] = RebasePointer(UniqHash[i], oldMap, newMap);
 
    for (auto i = Dynamic<pkgCache::PkgIterator>::toReMap.begin();
         i != Dynamic<pkgCache::PkgIterator>::toReMap.end(); ++i)
@@ -271,7 +272,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
 
       if (oldMap != Map.Data())
       {
-         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+         Last = RebasePointer(Last, oldMap, Map.Data());
          oldMap = Map.Data();
       }
 
@@ -297,7 +298,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
                               PackageName.c_str(), 1);
 
       if (oldMap != Map.Data())
-         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+         Last = RebasePointer(Last, oldMap, Map.Data());
       *Last = *verindex;
 
       Ver->ParentPkg = Pkg.Index();
@@ -605,7 +606,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
 	 OldDepLast = &D->NextDepends;
       OldDepVer = Ver;
    } else if (oldMap != Owner->Map.Data())
-      OldDepLast += (map_ptrloc*) Owner->Map.Data() - (map_ptrloc*) oldMap;
+      OldDepLast = RebasePointer(OldDepLast, oldMap, Owner->Map.Data());
 
    // Is it a file dependency?
    if (PackageName[0] == '/')
@@ -747,8 +748,8 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
 
    if (oldMap != Map.Data())
    {
-      Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
-      I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap;
+      Last = RebasePointer(Last, oldMap, Map.Data());
+      I = RebasePointer(I, oldMap, Map.Data());
    }
 
    *Last = *Item;
diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
new file mode 100644
index 0000000..efc4074
--- /dev/null
+++ b/apt/apt-pkg/rebase_pointer.h
@@ -0,0 +1,16 @@
+#ifndef PKGLIB_REBASE_POINTER_H
+#define PKGLIB_REBASE_POINTER_H
+
+template <typename T>
+static inline T* RebasePointer(T *ptr, const void * const old_base, const void * const new_base)
+{
+   return reinterpret_cast<T*>(reinterpret_cast<char*>(ptr) + (reinterpret_cast<char const * const>(new_base) - reinterpret_cast<char const * const>(old_base)));
+}
+
+template <typename T>
+static inline const T* RebasePointer(const T *ptr, const void * const old_base, const void * const new_base)
+{
+   return reinterpret_cast<const T*>(reinterpret_cast<const char*>(ptr) + (reinterpret_cast<char const * const>(new_base) - reinterpret_cast<char const * const>(old_base)));
+}
+
+#endif
diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc b/apt/apt-pkg/rpm/rpmlistparser.cc
index 9b2e9ad..84b6b8d 100644
--- a/apt/apt-pkg/rpm/rpmlistparser.cc
+++ b/apt/apt-pkg/rpm/rpmlistparser.cc
@@ -25,6 +25,7 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/crc-16.h>
 #include <apt-pkg/tagfile.h>
+#include <apt-pkg/rebase_pointer.h>
 
 #include <apti18n.h>
 
@@ -56,7 +57,7 @@ rpmListParser::rpmListParser(RPMHandler *Handler)
 
          for (auto iter: *SeenPackages)
          {
-            tmp.insert(iter + (static_cast<const char *>(newMap) - static_cast<const char *>(oldMap)));
+            tmp.insert(RebasePointer(iter, oldMap, newMap));
          }
 
          SeenPackages->swap(tmp);
-- 
2.24.0



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2] Fix pointer arithmetics
  2019-12-06 13:16 ` [devel] [PATCH for apt 2/2] Fix pointer arithmetics Aleksei Nikiforov
@ 2019-12-06 13:36   ` Ivan A. Melnikov
  2019-12-06 15:32     ` Aleksei Nikiforov
  2019-12-06 15:36     ` [devel] [PATCH for apt 2/2 v2] " Aleksei Nikiforov
  2019-12-08 23:31   ` [devel] [PATCH for apt 2/2] " Dmitry V. Levin
  2019-12-09 23:54   ` [devel] [PATCH apt 0/3] Fix 0.5.15lorg2-alt70~9 fallout Dmitry V. Levin
  2 siblings, 2 replies; 34+ messages in thread
From: Ivan A. Melnikov @ 2019-12-06 13:36 UTC (permalink / raw)
  To: ALT Linux Team development discussions; +Cc: Aleksei Nikiforov

On Fri, Dec 06, 2019 at 04:16:06PM +0300, Aleksei Nikiforov wrote:
> This change should fix pointer arithmetic issues for e2k.
> ---
>  apt/apt-pkg/Makefile.am          |  1 +
>  apt/apt-pkg/cacheiterators.h     | 14 ++++++++------
>  apt/apt-pkg/contrib/mmap.cc      |  8 +++++---
>  apt/apt-pkg/pkgcachegen.cc       | 15 ++++++++-------
>  apt/apt-pkg/rebase_pointer.h     | 16 ++++++++++++++++
>  apt/apt-pkg/rpm/rpmlistparser.cc |  3 ++-
>  6 files changed, 40 insertions(+), 17 deletions(-)
>  create mode 100644 apt/apt-pkg/rebase_pointer.h
> 
> diff --git a/apt/apt-pkg/Makefile.am b/apt/apt-pkg/Makefile.am
> index 4c0d234..d038d01 100644
> --- a/apt/apt-pkg/Makefile.am
> +++ b/apt/apt-pkg/Makefile.am
> @@ -94,6 +94,7 @@ libapt_pkg_la_SOURCES = \
>  	pkgsystem.h \
>  	policy.cc \
>  	policy.h \
> +	rebase_pointer.h \
>  	repository.cc \
>  	repository.h \
>  	scopeexit.h \
> diff --git a/apt/apt-pkg/cacheiterators.h b/apt/apt-pkg/cacheiterators.h
> index a4bf670..51f70c1 100644
> --- a/apt/apt-pkg/cacheiterators.h
> +++ b/apt/apt-pkg/cacheiterators.h
> @@ -34,6 +34,8 @@
>  #pragma interface "apt-pkg/cacheiterators.h"
>  #endif 
>  
> +#include <apt-pkg/rebase_pointer.h>
> +
>  #include <set>
>  
>  // Package Iterator
> @@ -89,7 +91,7 @@ class pkgCache::PkgIterator
>     {
>        if (Owner == 0 || Pkg == 0)
>           return;
> -      Pkg += static_cast<Package const *>(newMap) - static_cast<Package const *>(oldMap);
> +      Pkg = RebasePointer(Pkg, oldMap, newMap);
>     }
>  
>     // Constructors
> @@ -151,7 +153,7 @@ class pkgCache::VerIterator
>     {
>        if (Owner == 0 || Ver == 0)
>           return;
> -      Ver += static_cast<Version const *>(newMap) - static_cast<Version const *>(oldMap);
> +      Ver = RebasePointer(Ver, oldMap, newMap);
>     }
>  
>     inline VerIterator() : Ver(0), Owner(0) {};   
> @@ -224,7 +226,7 @@ class pkgCache::DepIterator
>     {
>        if (Owner == 0 || Dep == 0)
>           return;
> -      Dep += static_cast<Dependency const *>(newMap) - static_cast<Dependency const *>(oldMap);
> +      Dep = RebasePointer(Dep, oldMap, newMap);
>     }
>  
>     inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) :
> @@ -283,7 +285,7 @@ class pkgCache::PrvIterator
>     {
>        if (Owner == 0 || Prv == 0)
>           return;
> -      Prv += static_cast<Provides const *>(newMap) - static_cast<Provides const *>(oldMap);
> +      Prv = RebasePointer(Prv, oldMap, newMap);
>     }
>  
>     inline PrvIterator() : Prv(0), Type(PrvVer), Owner(0)  {};
> @@ -346,7 +348,7 @@ class pkgCache::PkgFileIterator
>     {
>        if (Owner == 0 || File == 0)
>           return;
> -      File += static_cast<PackageFile const *>(newMap) - static_cast<PackageFile const *>(oldMap);
> +      File = RebasePointer(File, oldMap, newMap);
>     }
>  
>     // Constructors
> @@ -387,7 +389,7 @@ class pkgCache::VerFileIterator
>     {
>        if (Owner == 0 || FileP == 0)
>           return;
> -      FileP += static_cast<VerFile const *>(newMap) - static_cast<VerFile const *>(oldMap);
> +      FileP = RebasePointer(FileP, oldMap, newMap);
>     }
>  
>     inline VerFileIterator() : Owner(0), FileP(0) {};
> diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
> index cf01be9..ddae2ff 100644
> --- a/apt/apt-pkg/contrib/mmap.cc
> +++ b/apt/apt-pkg/contrib/mmap.cc
> @@ -30,6 +30,7 @@
>  #include <apt-pkg/configuration.h>
>  #include <apt-pkg/mmap.h>
>  #include <apt-pkg/error.h>
> +#include <apt-pkg/rebase_pointer.h>
>  
>  #include <apti18n.h>
>  
> @@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
>        Pool* oldPools = Pools;
>        auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
>        if (Pools != oldPools)
> -         I += Pools - oldPools;
> +         I = RebasePointer(I, oldPools, Pools);
>  
>        // Does the allocation failed ?
>        if (!idxResult)
> @@ -371,7 +372,7 @@ bool DynamicMMap::Grow(unsigned long long size)
>        Fd->Write(&C,sizeof(C));
>     }
>  
> -   unsigned long const poolOffset = Pools - ((Pool*) Base);
> +   const void * const old_base = Base;
>  
>     if (Fd != 0)
>     {
> @@ -408,7 +409,8 @@ bool DynamicMMap::Grow(unsigned long long size)
>        memset((char*)Base + WorkSpace, 0, newSize - WorkSpace);
>     }
>  
> -   Pools = (Pool*) Base + poolOffset;
> +   if (Base != old_base)
> +      Pools = RebasePointer(Pools, old_base, Base);
>     WorkSpace = newSize;
>  
>     return true;
> diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc
> index 654c81c..10a0fd7 100644
> --- a/apt/apt-pkg/pkgcachegen.cc
> +++ b/apt/apt-pkg/pkgcachegen.cc
> @@ -26,6 +26,7 @@
>  #include <apt-pkg/strutl.h>
>  #include <apt-pkg/sptr.h>
>  #include <apt-pkg/pkgsystem.h>
> +#include <apt-pkg/rebase_pointer.h>
>  
>  #include <apti18n.h>
>  
> @@ -116,11 +117,11 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
>  
>     Cache.ReMap(false);
>  
> -   CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap;
> +   CurrentFile = RebasePointer(CurrentFile, oldMap, newMap);
>  
>     for (size_t i = 0; i < _count(UniqHash); ++i)
>        if (UniqHash[i] != 0)
> -         UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap;
> +         UniqHash[i] = RebasePointer(UniqHash[i], oldMap, newMap);
>  
>     for (auto i = Dynamic<pkgCache::PkgIterator>::toReMap.begin();
>          i != Dynamic<pkgCache::PkgIterator>::toReMap.end(); ++i)
> @@ -271,7 +272,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>  
>        if (oldMap != Map.Data())
>        {
> -         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
> +         Last = RebasePointer(Last, oldMap, Map.Data());
>           oldMap = Map.Data();
>        }
>  
> @@ -297,7 +298,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>                                PackageName.c_str(), 1);
>  
>        if (oldMap != Map.Data())
> -         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
> +         Last = RebasePointer(Last, oldMap, Map.Data());
>        *Last = *verindex;
>  
>        Ver->ParentPkg = Pkg.Index();
> @@ -605,7 +606,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
>  	 OldDepLast = &D->NextDepends;
>        OldDepVer = Ver;
>     } else if (oldMap != Owner->Map.Data())
> -      OldDepLast += (map_ptrloc*) Owner->Map.Data() - (map_ptrloc*) oldMap;
> +      OldDepLast = RebasePointer(OldDepLast, oldMap, Owner->Map.Data());
>  
>     // Is it a file dependency?
>     if (PackageName[0] == '/')
> @@ -747,8 +748,8 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
>  
>     if (oldMap != Map.Data())
>     {
> -      Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
> -      I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap;
> +      Last = RebasePointer(Last, oldMap, Map.Data());
> +      I = RebasePointer(I, oldMap, Map.Data());
>     }
>  
>     *Last = *Item;
> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
> new file mode 100644
> index 0000000..efc4074
> --- /dev/null
> +++ b/apt/apt-pkg/rebase_pointer.h
> @@ -0,0 +1,16 @@
> +#ifndef PKGLIB_REBASE_POINTER_H
> +#define PKGLIB_REBASE_POINTER_H
> +
> +template <typename T>
> +static inline T* RebasePointer(T *ptr, const void * const old_base, const void * const new_base)
> +{
> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(ptr) + (reinterpret_cast<char const * const>(new_base) - reinterpret_cast<char const * const>(old_base)));


AFAIR standard only allows to substract pointers to elements of the same
array. Wouldn't it be safer to first compute the offset of ptr with
respect to old_base and then add it to new_base?


> +}
> +
> +template <typename T>
> +static inline const T* RebasePointer(const T *ptr, const void * const old_base, const void * const new_base)
> +{
> +   return reinterpret_cast<const T*>(reinterpret_cast<const char*>(ptr) + (reinterpret_cast<char const * const>(new_base) - reinterpret_cast<char const * const>(old_base)));
> +}
> +
> +#endif
> diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc b/apt/apt-pkg/rpm/rpmlistparser.cc
> index 9b2e9ad..84b6b8d 100644
> --- a/apt/apt-pkg/rpm/rpmlistparser.cc
> +++ b/apt/apt-pkg/rpm/rpmlistparser.cc
> @@ -25,6 +25,7 @@
>  #include <apt-pkg/strutl.h>
>  #include <apt-pkg/crc-16.h>
>  #include <apt-pkg/tagfile.h>
> +#include <apt-pkg/rebase_pointer.h>
>  
>  #include <apti18n.h>
>  
> @@ -56,7 +57,7 @@ rpmListParser::rpmListParser(RPMHandler *Handler)
>  
>           for (auto iter: *SeenPackages)
>           {
> -            tmp.insert(iter + (static_cast<const char *>(newMap) - static_cast<const char *>(oldMap)));
> +            tmp.insert(RebasePointer(iter, oldMap, newMap));
>           }
>  
>           SeenPackages->swap(tmp);
> -- 
> 2.24.0
> 
> _______________________________________________
> Devel mailing list
> Devel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2] Fix pointer arithmetics
  2019-12-06 13:36   ` Ivan A. Melnikov
@ 2019-12-06 15:32     ` Aleksei Nikiforov
  2019-12-06 15:36     ` [devel] [PATCH for apt 2/2 v2] " Aleksei Nikiforov
  1 sibling, 0 replies; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-06 15:32 UTC (permalink / raw)
  To: devel

06.12.2019 16:36, Ivan A. Melnikov пишет:
> On Fri, Dec 06, 2019 at 04:16:06PM +0300, Aleksei Nikiforov wrote:
>> This change should fix pointer arithmetic issues for e2k.
>> ---
>>   apt/apt-pkg/Makefile.am          |  1 +
>>   apt/apt-pkg/cacheiterators.h     | 14 ++++++++------
>>   apt/apt-pkg/contrib/mmap.cc      |  8 +++++---
>>   apt/apt-pkg/pkgcachegen.cc       | 15 ++++++++-------
>>   apt/apt-pkg/rebase_pointer.h     | 16 ++++++++++++++++
>>   apt/apt-pkg/rpm/rpmlistparser.cc |  3 ++-
>>   6 files changed, 40 insertions(+), 17 deletions(-)
>>   create mode 100644 apt/apt-pkg/rebase_pointer.h
>>
>> diff --git a/apt/apt-pkg/Makefile.am b/apt/apt-pkg/Makefile.am
>> index 4c0d234..d038d01 100644
>> --- a/apt/apt-pkg/Makefile.am
>> +++ b/apt/apt-pkg/Makefile.am
>> @@ -94,6 +94,7 @@ libapt_pkg_la_SOURCES = \
>>   	pkgsystem.h \
>>   	policy.cc \
>>   	policy.h \
>> +	rebase_pointer.h \
>>   	repository.cc \
>>   	repository.h \
>>   	scopeexit.h \
>> diff --git a/apt/apt-pkg/cacheiterators.h b/apt/apt-pkg/cacheiterators.h
>> index a4bf670..51f70c1 100644
>> --- a/apt/apt-pkg/cacheiterators.h
>> +++ b/apt/apt-pkg/cacheiterators.h
>> @@ -34,6 +34,8 @@
>>   #pragma interface "apt-pkg/cacheiterators.h"
>>   #endif
>>   
>> +#include <apt-pkg/rebase_pointer.h>
>> +
>>   #include <set>
>>   
>>   // Package Iterator
>> @@ -89,7 +91,7 @@ class pkgCache::PkgIterator
>>      {
>>         if (Owner == 0 || Pkg == 0)
>>            return;
>> -      Pkg += static_cast<Package const *>(newMap) - static_cast<Package const *>(oldMap);
>> +      Pkg = RebasePointer(Pkg, oldMap, newMap);
>>      }
>>   
>>      // Constructors
>> @@ -151,7 +153,7 @@ class pkgCache::VerIterator
>>      {
>>         if (Owner == 0 || Ver == 0)
>>            return;
>> -      Ver += static_cast<Version const *>(newMap) - static_cast<Version const *>(oldMap);
>> +      Ver = RebasePointer(Ver, oldMap, newMap);
>>      }
>>   
>>      inline VerIterator() : Ver(0), Owner(0) {};
>> @@ -224,7 +226,7 @@ class pkgCache::DepIterator
>>      {
>>         if (Owner == 0 || Dep == 0)
>>            return;
>> -      Dep += static_cast<Dependency const *>(newMap) - static_cast<Dependency const *>(oldMap);
>> +      Dep = RebasePointer(Dep, oldMap, newMap);
>>      }
>>   
>>      inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) :
>> @@ -283,7 +285,7 @@ class pkgCache::PrvIterator
>>      {
>>         if (Owner == 0 || Prv == 0)
>>            return;
>> -      Prv += static_cast<Provides const *>(newMap) - static_cast<Provides const *>(oldMap);
>> +      Prv = RebasePointer(Prv, oldMap, newMap);
>>      }
>>   
>>      inline PrvIterator() : Prv(0), Type(PrvVer), Owner(0)  {};
>> @@ -346,7 +348,7 @@ class pkgCache::PkgFileIterator
>>      {
>>         if (Owner == 0 || File == 0)
>>            return;
>> -      File += static_cast<PackageFile const *>(newMap) - static_cast<PackageFile const *>(oldMap);
>> +      File = RebasePointer(File, oldMap, newMap);
>>      }
>>   
>>      // Constructors
>> @@ -387,7 +389,7 @@ class pkgCache::VerFileIterator
>>      {
>>         if (Owner == 0 || FileP == 0)
>>            return;
>> -      FileP += static_cast<VerFile const *>(newMap) - static_cast<VerFile const *>(oldMap);
>> +      FileP = RebasePointer(FileP, oldMap, newMap);
>>      }
>>   
>>      inline VerFileIterator() : Owner(0), FileP(0) {};
>> diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
>> index cf01be9..ddae2ff 100644
>> --- a/apt/apt-pkg/contrib/mmap.cc
>> +++ b/apt/apt-pkg/contrib/mmap.cc
>> @@ -30,6 +30,7 @@
>>   #include <apt-pkg/configuration.h>
>>   #include <apt-pkg/mmap.h>
>>   #include <apt-pkg/error.h>
>> +#include <apt-pkg/rebase_pointer.h>
>>   
>>   #include <apti18n.h>
>>   
>> @@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
>>         Pool* oldPools = Pools;
>>         auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
>>         if (Pools != oldPools)
>> -         I += Pools - oldPools;
>> +         I = RebasePointer(I, oldPools, Pools);
>>   
>>         // Does the allocation failed ?
>>         if (!idxResult)
>> @@ -371,7 +372,7 @@ bool DynamicMMap::Grow(unsigned long long size)
>>         Fd->Write(&C,sizeof(C));
>>      }
>>   
>> -   unsigned long const poolOffset = Pools - ((Pool*) Base);
>> +   const void * const old_base = Base;
>>   
>>      if (Fd != 0)
>>      {
>> @@ -408,7 +409,8 @@ bool DynamicMMap::Grow(unsigned long long size)
>>         memset((char*)Base + WorkSpace, 0, newSize - WorkSpace);
>>      }
>>   
>> -   Pools = (Pool*) Base + poolOffset;
>> +   if (Base != old_base)
>> +      Pools = RebasePointer(Pools, old_base, Base);
>>      WorkSpace = newSize;
>>   
>>      return true;
>> diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc
>> index 654c81c..10a0fd7 100644
>> --- a/apt/apt-pkg/pkgcachegen.cc
>> +++ b/apt/apt-pkg/pkgcachegen.cc
>> @@ -26,6 +26,7 @@
>>   #include <apt-pkg/strutl.h>
>>   #include <apt-pkg/sptr.h>
>>   #include <apt-pkg/pkgsystem.h>
>> +#include <apt-pkg/rebase_pointer.h>
>>   
>>   #include <apti18n.h>
>>   
>> @@ -116,11 +117,11 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
>>   
>>      Cache.ReMap(false);
>>   
>> -   CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap;
>> +   CurrentFile = RebasePointer(CurrentFile, oldMap, newMap);
>>   
>>      for (size_t i = 0; i < _count(UniqHash); ++i)
>>         if (UniqHash[i] != 0)
>> -         UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap;
>> +         UniqHash[i] = RebasePointer(UniqHash[i], oldMap, newMap);
>>   
>>      for (auto i = Dynamic<pkgCache::PkgIterator>::toReMap.begin();
>>           i != Dynamic<pkgCache::PkgIterator>::toReMap.end(); ++i)
>> @@ -271,7 +272,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>>   
>>         if (oldMap != Map.Data())
>>         {
>> -         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
>> +         Last = RebasePointer(Last, oldMap, Map.Data());
>>            oldMap = Map.Data();
>>         }
>>   
>> @@ -297,7 +298,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>>                                 PackageName.c_str(), 1);
>>   
>>         if (oldMap != Map.Data())
>> -         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
>> +         Last = RebasePointer(Last, oldMap, Map.Data());
>>         *Last = *verindex;
>>   
>>         Ver->ParentPkg = Pkg.Index();
>> @@ -605,7 +606,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
>>   	 OldDepLast = &D->NextDepends;
>>         OldDepVer = Ver;
>>      } else if (oldMap != Owner->Map.Data())
>> -      OldDepLast += (map_ptrloc*) Owner->Map.Data() - (map_ptrloc*) oldMap;
>> +      OldDepLast = RebasePointer(OldDepLast, oldMap, Owner->Map.Data());
>>   
>>      // Is it a file dependency?
>>      if (PackageName[0] == '/')
>> @@ -747,8 +748,8 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
>>   
>>      if (oldMap != Map.Data())
>>      {
>> -      Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
>> -      I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap;
>> +      Last = RebasePointer(Last, oldMap, Map.Data());
>> +      I = RebasePointer(I, oldMap, Map.Data());
>>      }
>>   
>>      *Last = *Item;
>> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
>> new file mode 100644
>> index 0000000..efc4074
>> --- /dev/null
>> +++ b/apt/apt-pkg/rebase_pointer.h
>> @@ -0,0 +1,16 @@
>> +#ifndef PKGLIB_REBASE_POINTER_H
>> +#define PKGLIB_REBASE_POINTER_H
>> +
>> +template <typename T>
>> +static inline T* RebasePointer(T *ptr, const void * const old_base, const void * const new_base)
>> +{
>> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(ptr) + (reinterpret_cast<char const * const>(new_base) - reinterpret_cast<char const * const>(old_base)));
> 
> 
> AFAIR standard only allows to substract pointers to elements of the same
> array. Wouldn't it be safer to first compute the offset of ptr with
> respect to old_base and then add it to new_base?
> 
> 

It can be done. Arithmetically it should be same result, but it'd also 
take some changes to get rid of 'const' specifiers since they'd clash 
with non-const variables (ptr).

-   return reinterpret_cast<T*>(reinterpret_cast<char*>(ptr) + 
(reinterpret_cast<char const * const>(new_base) - reinterpret_cast<char 
const * const>(old_base)));
+   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base) + 
(reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(old_base)));


>> +}
>> +
>> +template <typename T>
>> +static inline const T* RebasePointer(const T *ptr, const void * const old_base, const void * const new_base)
>> +{
>> +   return reinterpret_cast<const T*>(reinterpret_cast<const char*>(ptr) + (reinterpret_cast<char const * const>(new_base) - reinterpret_cast<char const * const>(old_base)));
>> +}
>> +
>> +#endif
>> diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc b/apt/apt-pkg/rpm/rpmlistparser.cc
>> index 9b2e9ad..84b6b8d 100644
>> --- a/apt/apt-pkg/rpm/rpmlistparser.cc
>> +++ b/apt/apt-pkg/rpm/rpmlistparser.cc
>> @@ -25,6 +25,7 @@
>>   #include <apt-pkg/strutl.h>
>>   #include <apt-pkg/crc-16.h>
>>   #include <apt-pkg/tagfile.h>
>> +#include <apt-pkg/rebase_pointer.h>
>>   
>>   #include <apti18n.h>
>>   
>> @@ -56,7 +57,7 @@ rpmListParser::rpmListParser(RPMHandler *Handler)
>>   
>>            for (auto iter: *SeenPackages)
>>            {
>> -            tmp.insert(iter + (static_cast<const char *>(newMap) - static_cast<const char *>(oldMap)));
>> +            tmp.insert(RebasePointer(iter, oldMap, newMap));
>>            }
>>   
>>            SeenPackages->swap(tmp);
>> -- 
>> 2.24.0
>>
>> _______________________________________________
>> Devel mailing list
>> Devel@lists.altlinux.org
>> https://lists.altlinux.org/mailman/listinfo/devel
> _______________________________________________
> Devel mailing list
> Devel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel
> 


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-06 13:36   ` Ivan A. Melnikov
  2019-12-06 15:32     ` Aleksei Nikiforov
@ 2019-12-06 15:36     ` Aleksei Nikiforov
  2019-12-07 14:52       ` Andrey Savchenko
  2019-12-08 23:21       ` Dmitry V. Levin
  1 sibling, 2 replies; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-06 15:36 UTC (permalink / raw)
  To: devel; +Cc: Aleksei Nikiforov

This change should fix pointer arithmetic issues for e2k.
---
 apt/apt-pkg/Makefile.am           |  1 +
 apt/apt-pkg/cacheiterators.h      | 26 ++++++++++++++------------
 apt/apt-pkg/contrib/mmap.cc       |  8 +++++---
 apt/apt-pkg/pkgcachegen.cc        | 29 +++++++++++++++--------------
 apt/apt-pkg/pkgcachegen.h         |  6 +++---
 apt/apt-pkg/rebase_pointer.h      | 16 ++++++++++++++++
 apt/apt-pkg/rpm/rpmlistparser.cc  |  5 +++--
 apt/apt-pkg/rpm/rpmpackagedata.cc |  2 +-
 8 files changed, 58 insertions(+), 35 deletions(-)
 create mode 100644 apt/apt-pkg/rebase_pointer.h

diff --git a/apt/apt-pkg/Makefile.am b/apt/apt-pkg/Makefile.am
index 4c0d234..d038d01 100644
--- a/apt/apt-pkg/Makefile.am
+++ b/apt/apt-pkg/Makefile.am
@@ -94,6 +94,7 @@ libapt_pkg_la_SOURCES = \
 	pkgsystem.h \
 	policy.cc \
 	policy.h \
+	rebase_pointer.h \
 	repository.cc \
 	repository.h \
 	scopeexit.h \
diff --git a/apt/apt-pkg/cacheiterators.h b/apt/apt-pkg/cacheiterators.h
index a4bf670..118838e 100644
--- a/apt/apt-pkg/cacheiterators.h
+++ b/apt/apt-pkg/cacheiterators.h
@@ -34,6 +34,8 @@
 #pragma interface "apt-pkg/cacheiterators.h"
 #endif 
 
+#include <apt-pkg/rebase_pointer.h>
+
 #include <set>
 
 // Package Iterator
@@ -85,11 +87,11 @@ class pkgCache::PkgIterator
    inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
    OkState State() const;
 
-   void ReMap(void const * const oldMap, void const * const newMap)
+   void ReMap(void *oldMap, void *newMap)
    {
       if (Owner == 0 || Pkg == 0)
          return;
-      Pkg += static_cast<Package const *>(newMap) - static_cast<Package const *>(oldMap);
+      Pkg = RebasePointer(Pkg, oldMap, newMap);
    }
 
    // Constructors
@@ -147,11 +149,11 @@ class pkgCache::VerIterator
    bool Automatic() const;
    VerFileIterator NewestFile() const;
 
-   void ReMap(void const * const oldMap, void const * const newMap)
+   void ReMap(void *oldMap, void *newMap)
    {
       if (Owner == 0 || Ver == 0)
          return;
-      Ver += static_cast<Version const *>(newMap) - static_cast<Version const *>(oldMap);
+      Ver = RebasePointer(Ver, oldMap, newMap);
    }
 
    inline VerIterator() : Ver(0), Owner(0) {};   
@@ -220,11 +222,11 @@ class pkgCache::DepIterator
    inline const char *CompType() {return Owner->CompType(Dep->CompareOp);};
    inline const char *DepType() {return Owner->DepType(Dep->Type);};
 
-   void ReMap(void const * const oldMap, void const * const newMap)
+   void ReMap(void *oldMap, void *newMap)
    {
       if (Owner == 0 || Dep == 0)
          return;
-      Dep += static_cast<Dependency const *>(newMap) - static_cast<Dependency const *>(oldMap);
+      Dep = RebasePointer(Dep, oldMap, newMap);
    }
 
    inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) :
@@ -279,11 +281,11 @@ class pkgCache::PrvIterator
    inline PkgIterator OwnerPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[Prv->Version].ParentPkg);};
    inline unsigned long long Index() const {return Prv - Owner->ProvideP;};
 
-   void ReMap(void const * const oldMap, void const * const newMap)
+   void ReMap(void *oldMap, void *newMap)
    {
       if (Owner == 0 || Prv == 0)
          return;
-      Prv += static_cast<Provides const *>(newMap) - static_cast<Provides const *>(oldMap);
+      Prv = RebasePointer(Prv, oldMap, newMap);
    }
 
    inline PrvIterator() : Prv(0), Type(PrvVer), Owner(0)  {};
@@ -342,11 +344,11 @@ class pkgCache::PkgFileIterator
    bool IsOk();
    string RelStr();
 
-   void ReMap(void const * const oldMap, void const * const newMap)
+   void ReMap(void *oldMap, void *newMap)
    {
       if (Owner == 0 || File == 0)
          return;
-      File += static_cast<PackageFile const *>(newMap) - static_cast<PackageFile const *>(oldMap);
+      File = RebasePointer(File, oldMap, newMap);
    }
 
    // Constructors
@@ -383,11 +385,11 @@ class pkgCache::VerFileIterator
    inline PkgFileIterator File() const {return PkgFileIterator(*Owner,FileP->File + Owner->PkgFileP);};
    inline unsigned long long Index() const {return FileP - Owner->VerFileP;};
 
-   void ReMap(void const * const oldMap, void const * const newMap)
+   void ReMap(void *oldMap, void *newMap)
    {
       if (Owner == 0 || FileP == 0)
          return;
-      FileP += static_cast<VerFile const *>(newMap) - static_cast<VerFile const *>(oldMap);
+      FileP = RebasePointer(FileP, oldMap, newMap);
    }
 
    inline VerFileIterator() : Owner(0), FileP(0) {};
diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
index cf01be9..35f1a25 100644
--- a/apt/apt-pkg/contrib/mmap.cc
+++ b/apt/apt-pkg/contrib/mmap.cc
@@ -30,6 +30,7 @@
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/mmap.h>
 #include <apt-pkg/error.h>
+#include <apt-pkg/rebase_pointer.h>
 
 #include <apti18n.h>
 
@@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
       Pool* oldPools = Pools;
       auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
       if (Pools != oldPools)
-         I += Pools - oldPools;
+         I = RebasePointer(I, oldPools, Pools);
 
       // Does the allocation failed ?
       if (!idxResult)
@@ -371,7 +372,7 @@ bool DynamicMMap::Grow(unsigned long long size)
       Fd->Write(&C,sizeof(C));
    }
 
-   unsigned long const poolOffset = Pools - ((Pool*) Base);
+   void *old_base = Base;
 
    if (Fd != 0)
    {
@@ -408,7 +409,8 @@ bool DynamicMMap::Grow(unsigned long long size)
       memset((char*)Base + WorkSpace, 0, newSize - WorkSpace);
    }
 
-   Pools = (Pool*) Base + poolOffset;
+   if (Base != old_base)
+      Pools = RebasePointer(Pools, old_base, Base);
    WorkSpace = newSize;
 
    return true;
diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc
index 654c81c..37364e9 100644
--- a/apt/apt-pkg/pkgcachegen.cc
+++ b/apt/apt-pkg/pkgcachegen.cc
@@ -26,6 +26,7 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/rebase_pointer.h>
 
 #include <apti18n.h>
 
@@ -109,18 +110,18 @@ pkgCacheGenerator::~pkgCacheGenerator()
    Map.Sync(0,sizeof(pkgCache::Header));
 }
 									/*}}}*/
-void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newMap)
+void pkgCacheGenerator::ReMap(void *oldMap, void *newMap)
 {
    if (oldMap == newMap)
       return;
 
    Cache.ReMap(false);
 
-   CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap;
+   CurrentFile = RebasePointer(CurrentFile, oldMap, newMap);
 
    for (size_t i = 0; i < _count(UniqHash); ++i)
       if (UniqHash[i] != 0)
-         UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap;
+         UniqHash[i] = RebasePointer(UniqHash[i], oldMap, newMap);
 
    for (auto i = Dynamic<pkgCache::PkgIterator>::toReMap.begin();
         i != Dynamic<pkgCache::PkgIterator>::toReMap.end(); ++i)
@@ -147,7 +148,7 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
 // CacheGenerator::WriteStringInMap					/*{{{*/
 std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(const char *String,
 					unsigned long Len) {
-   void const * const oldMap = Map.Data();
+   void *oldMap = Map.Data();
    const auto index = Map.WriteString(String, Len);
    if (index)
       ReMap(oldMap, Map.Data());
@@ -156,7 +157,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(cons
 									/*}}}*/
 // CacheGenerator::WriteStringInMap					/*{{{*/
 std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(const char *String) {
-   void const * const oldMap = Map.Data();
+   void *oldMap = Map.Data();
    const auto index = Map.WriteString(String);
    if (index)
       ReMap(oldMap, Map.Data());
@@ -164,7 +165,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(cons
 }
 									/*}}}*/
 std::experimental::optional<map_ptrloc> pkgCacheGenerator::AllocateInMap(unsigned long size) {/*{{{*/
-   void const * const oldMap = Map.Data();
+   void *oldMap = Map.Data();
    const auto index = Map.Allocate(size);
    if (index)
       ReMap(oldMap, Map.Data());
@@ -229,7 +230,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
       pkgCache::VerIterator Ver = Pkg.VersionList();
       Dynamic<pkgCache::VerIterator> DynVer(Ver);
       map_ptrloc *Last = &Pkg->VersionList;
-      const void * oldMap = Map.Data();
+      void *oldMap = Map.Data();
       int Res = 1;
       for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
       {
@@ -271,7 +272,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
 
       if (oldMap != Map.Data())
       {
-         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+         Last = RebasePointer(Last, oldMap, Map.Data());
          oldMap = Map.Data();
       }
 
@@ -297,7 +298,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
                               PackageName.c_str(), 1);
 
       if (oldMap != Map.Data())
-         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+         Last = RebasePointer(Last, oldMap, Map.Data());
       *Last = *verindex;
 
       Ver->ParentPkg = Pkg.Index();
@@ -553,7 +554,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
 					       unsigned int Op,
 					       unsigned int Type)
 {
-   void const * const oldMap = Owner->Map.Data();
+   void *oldMap = Owner->Map.Data();
    pkgCache &Cache = Owner->Cache;
    
    // Get a structure
@@ -605,7 +606,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
 	 OldDepLast = &D->NextDepends;
       OldDepVer = Ver;
    } else if (oldMap != Owner->Map.Data())
-      OldDepLast += (map_ptrloc*) Owner->Map.Data() - (map_ptrloc*) oldMap;
+      OldDepLast = RebasePointer(OldDepLast, oldMap, Owner->Map.Data());
 
    // Is it a file dependency?
    if (PackageName[0] == '/')
@@ -739,7 +740,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
    }
    
    // Get a structure
-   void const * const oldMap = Map.Data();
+   void *oldMap = Map.Data();
    const auto Item = AllocateInMap(sizeof(pkgCache::StringItem));
    const auto idxString = WriteStringInMap(S, Size);
    if ((!Item) || (!idxString))
@@ -747,8 +748,8 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
 
    if (oldMap != Map.Data())
    {
-      Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
-      I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap;
+      Last = RebasePointer(Last, oldMap, Map.Data());
+      I = RebasePointer(I, oldMap, Map.Data());
    }
 
    *Last = *Item;
diff --git a/apt/apt-pkg/pkgcachegen.h b/apt/apt-pkg/pkgcachegen.h
index 77075a6..0faf6e1 100644
--- a/apt/apt-pkg/pkgcachegen.h
+++ b/apt/apt-pkg/pkgcachegen.h
@@ -72,7 +72,7 @@ class pkgCacheGenerator
    class DynamicFunction
    {
    public:
-      typedef std::function<void(const void *, const void *)> function;
+      typedef std::function<void(void *, void *)> function;
 
       static std::set<DynamicFunction*> toReMap;
 
@@ -93,7 +93,7 @@ class pkgCacheGenerator
          toReMap.erase(this);
       }
 
-      void call(const void *oldMap, const void *newMap)
+      void call(void *oldMap, void *newMap)
       {
          if (m_function)
             m_function(oldMap, newMap);
@@ -140,7 +140,7 @@ class pkgCacheGenerator
    // CNC:2003-03-18
    inline void ResetFileDeps() {FoundFileDeps = false;};
 
-   void ReMap(void const * const oldMap, void const * const newMap);
+   void ReMap(void *oldMap, void *newMap);
 
    pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress);
    ~pkgCacheGenerator();
diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
new file mode 100644
index 0000000..f6b3c15
--- /dev/null
+++ b/apt/apt-pkg/rebase_pointer.h
@@ -0,0 +1,16 @@
+#ifndef PKGLIB_REBASE_POINTER_H
+#define PKGLIB_REBASE_POINTER_H
+
+template <typename T>
+static inline T* RebasePointer(T *ptr, void *old_base, void *new_base)
+{
+   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(old_base)));
+}
+
+template <typename T>
+static inline const T* RebasePointer(const T *ptr, void *old_base, void *new_base)
+{
+   return reinterpret_cast<const T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<const char*>(ptr) - reinterpret_cast<char*>(old_base)));
+}
+
+#endif
diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc b/apt/apt-pkg/rpm/rpmlistparser.cc
index 9b2e9ad..bd13b99 100644
--- a/apt/apt-pkg/rpm/rpmlistparser.cc
+++ b/apt/apt-pkg/rpm/rpmlistparser.cc
@@ -25,6 +25,7 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/crc-16.h>
 #include <apt-pkg/tagfile.h>
+#include <apt-pkg/rebase_pointer.h>
 
 #include <apti18n.h>
 
@@ -50,13 +51,13 @@ rpmListParser::rpmListParser(RPMHandler *Handler)
    {
       SeenPackages.reset(new SeenPackagesType);
       m_SeenPackagesRealloc.reset(new pkgCacheGenerator::DynamicFunction(
-         [this] (void const *oldMap, void const *newMap)
+         [this] (void *oldMap, void *newMap)
       {
          SeenPackagesType tmp;
 
          for (auto iter: *SeenPackages)
          {
-            tmp.insert(iter + (static_cast<const char *>(newMap) - static_cast<const char *>(oldMap)));
+            tmp.insert(RebasePointer(iter, oldMap, newMap));
          }
 
          SeenPackages->swap(tmp);
diff --git a/apt/apt-pkg/rpm/rpmpackagedata.cc b/apt/apt-pkg/rpm/rpmpackagedata.cc
index 61c15d5..d6c677b 100644
--- a/apt/apt-pkg/rpm/rpmpackagedata.cc
+++ b/apt/apt-pkg/rpm/rpmpackagedata.cc
@@ -23,7 +23,7 @@ RPMPackageData::RPMPackageData()
 #endif
 {
    m_VerMapRealloc.reset(new pkgCacheGenerator::DynamicFunction(
-      [this] (void const *oldMap, void const *newMap)
+      [this] (void *oldMap, void *newMap)
    {
       for (auto iter1 = VerMap.begin(); iter1 != VerMap.end(); ++iter1)
       {
-- 
2.24.0



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-06 15:36     ` [devel] [PATCH for apt 2/2 v2] " Aleksei Nikiforov
@ 2019-12-07 14:52       ` Andrey Savchenko
  2019-12-08 22:56         ` Dmitry V. Levin
  2019-12-09  6:54         ` Aleksei Nikiforov
  2019-12-08 23:21       ` Dmitry V. Levin
  1 sibling, 2 replies; 34+ messages in thread
From: Andrey Savchenko @ 2019-12-07 14:52 UTC (permalink / raw)
  To: ALT Linux Team development discussions

[-- Attachment #1: Type: text/plain, Size: 15582 bytes --]

Hi all!

On Fri,  6 Dec 2019 18:36:55 +0300 Aleksei Nikiforov wrote:
> This change should fix pointer arithmetic issues for e2k.

This commit message is misleading. Pointer arithmetic is broken on
all architectures, but by pure chance in happens to work correctly
when gcc is used. On e2k the lcc compiler is used, so problem
manifests itself. But this doesn't change the fact that pointer
arithmetic was flawed on all architectures.

> ---
>  apt/apt-pkg/Makefile.am           |  1 +
>  apt/apt-pkg/cacheiterators.h      | 26 ++++++++++++++------------
>  apt/apt-pkg/contrib/mmap.cc       |  8 +++++---
>  apt/apt-pkg/pkgcachegen.cc        | 29 +++++++++++++++--------------
>  apt/apt-pkg/pkgcachegen.h         |  6 +++---
>  apt/apt-pkg/rebase_pointer.h      | 16 ++++++++++++++++
>  apt/apt-pkg/rpm/rpmlistparser.cc  |  5 +++--
>  apt/apt-pkg/rpm/rpmpackagedata.cc |  2 +-
>  8 files changed, 58 insertions(+), 35 deletions(-)
>  create mode 100644 apt/apt-pkg/rebase_pointer.h
> 
> diff --git a/apt/apt-pkg/Makefile.am b/apt/apt-pkg/Makefile.am
> index 4c0d234..d038d01 100644
> --- a/apt/apt-pkg/Makefile.am
> +++ b/apt/apt-pkg/Makefile.am
> @@ -94,6 +94,7 @@ libapt_pkg_la_SOURCES = \
>  	pkgsystem.h \
>  	policy.cc \
>  	policy.h \
> +	rebase_pointer.h \
>  	repository.cc \
>  	repository.h \
>  	scopeexit.h \
> diff --git a/apt/apt-pkg/cacheiterators.h b/apt/apt-pkg/cacheiterators.h
> index a4bf670..118838e 100644
> --- a/apt/apt-pkg/cacheiterators.h
> +++ b/apt/apt-pkg/cacheiterators.h
> @@ -34,6 +34,8 @@
>  #pragma interface "apt-pkg/cacheiterators.h"
>  #endif 
>  
> +#include <apt-pkg/rebase_pointer.h>
> +
>  #include <set>
>  
>  // Package Iterator
> @@ -85,11 +87,11 @@ class pkgCache::PkgIterator
>     inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
>     OkState State() const;
>  
> -   void ReMap(void const * const oldMap, void const * const newMap)
> +   void ReMap(void *oldMap, void *newMap)
>     {
>        if (Owner == 0 || Pkg == 0)
>           return;
> -      Pkg += static_cast<Package const *>(newMap) - static_cast<Package const *>(oldMap);
> +      Pkg = RebasePointer(Pkg, oldMap, newMap);
>     }
>  
>     // Constructors
> @@ -147,11 +149,11 @@ class pkgCache::VerIterator
>     bool Automatic() const;
>     VerFileIterator NewestFile() const;
>  
> -   void ReMap(void const * const oldMap, void const * const newMap)
> +   void ReMap(void *oldMap, void *newMap)
>     {
>        if (Owner == 0 || Ver == 0)
>           return;
> -      Ver += static_cast<Version const *>(newMap) - static_cast<Version const *>(oldMap);
> +      Ver = RebasePointer(Ver, oldMap, newMap);
>     }
>  
>     inline VerIterator() : Ver(0), Owner(0) {};   
> @@ -220,11 +222,11 @@ class pkgCache::DepIterator
>     inline const char *CompType() {return Owner->CompType(Dep->CompareOp);};
>     inline const char *DepType() {return Owner->DepType(Dep->Type);};
>  
> -   void ReMap(void const * const oldMap, void const * const newMap)
> +   void ReMap(void *oldMap, void *newMap)
>     {
>        if (Owner == 0 || Dep == 0)
>           return;
> -      Dep += static_cast<Dependency const *>(newMap) - static_cast<Dependency const *>(oldMap);
> +      Dep = RebasePointer(Dep, oldMap, newMap);
>     }
>  
>     inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) :
> @@ -279,11 +281,11 @@ class pkgCache::PrvIterator
>     inline PkgIterator OwnerPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[Prv->Version].ParentPkg);};
>     inline unsigned long long Index() const {return Prv - Owner->ProvideP;};
>  
> -   void ReMap(void const * const oldMap, void const * const newMap)
> +   void ReMap(void *oldMap, void *newMap)
>     {
>        if (Owner == 0 || Prv == 0)
>           return;
> -      Prv += static_cast<Provides const *>(newMap) - static_cast<Provides const *>(oldMap);
> +      Prv = RebasePointer(Prv, oldMap, newMap);
>     }
>  
>     inline PrvIterator() : Prv(0), Type(PrvVer), Owner(0)  {};
> @@ -342,11 +344,11 @@ class pkgCache::PkgFileIterator
>     bool IsOk();
>     string RelStr();
>  
> -   void ReMap(void const * const oldMap, void const * const newMap)
> +   void ReMap(void *oldMap, void *newMap)
>     {
>        if (Owner == 0 || File == 0)
>           return;
> -      File += static_cast<PackageFile const *>(newMap) - static_cast<PackageFile const *>(oldMap);
> +      File = RebasePointer(File, oldMap, newMap);
>     }
>  
>     // Constructors
> @@ -383,11 +385,11 @@ class pkgCache::VerFileIterator
>     inline PkgFileIterator File() const {return PkgFileIterator(*Owner,FileP->File + Owner->PkgFileP);};
>     inline unsigned long long Index() const {return FileP - Owner->VerFileP;};
>  
> -   void ReMap(void const * const oldMap, void const * const newMap)
> +   void ReMap(void *oldMap, void *newMap)
>     {
>        if (Owner == 0 || FileP == 0)
>           return;
> -      FileP += static_cast<VerFile const *>(newMap) - static_cast<VerFile const *>(oldMap);
> +      FileP = RebasePointer(FileP, oldMap, newMap);
>     }
>  
>     inline VerFileIterator() : Owner(0), FileP(0) {};
> diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
> index cf01be9..35f1a25 100644
> --- a/apt/apt-pkg/contrib/mmap.cc
> +++ b/apt/apt-pkg/contrib/mmap.cc
> @@ -30,6 +30,7 @@
>  #include <apt-pkg/configuration.h>
>  #include <apt-pkg/mmap.h>
>  #include <apt-pkg/error.h>
> +#include <apt-pkg/rebase_pointer.h>
>  
>  #include <apti18n.h>
>  
> @@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
>        Pool* oldPools = Pools;
>        auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
>        if (Pools != oldPools)
> -         I += Pools - oldPools;
> +         I = RebasePointer(I, oldPools, Pools);
>  
>        // Does the allocation failed ?
>        if (!idxResult)
> @@ -371,7 +372,7 @@ bool DynamicMMap::Grow(unsigned long long size)
>        Fd->Write(&C,sizeof(C));
>     }
>  
> -   unsigned long const poolOffset = Pools - ((Pool*) Base);
> +   void *old_base = Base;
>  
>     if (Fd != 0)
>     {
> @@ -408,7 +409,8 @@ bool DynamicMMap::Grow(unsigned long long size)
>        memset((char*)Base + WorkSpace, 0, newSize - WorkSpace);
>     }
>  
> -   Pools = (Pool*) Base + poolOffset;
> +   if (Base != old_base)
> +      Pools = RebasePointer(Pools, old_base, Base);
>     WorkSpace = newSize;
>  
>     return true;
> diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc
> index 654c81c..37364e9 100644
> --- a/apt/apt-pkg/pkgcachegen.cc
> +++ b/apt/apt-pkg/pkgcachegen.cc
> @@ -26,6 +26,7 @@
>  #include <apt-pkg/strutl.h>
>  #include <apt-pkg/sptr.h>
>  #include <apt-pkg/pkgsystem.h>
> +#include <apt-pkg/rebase_pointer.h>
>  
>  #include <apti18n.h>
>  
> @@ -109,18 +110,18 @@ pkgCacheGenerator::~pkgCacheGenerator()
>     Map.Sync(0,sizeof(pkgCache::Header));
>  }
>  									/*}}}*/
> -void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newMap)
> +void pkgCacheGenerator::ReMap(void *oldMap, void *newMap)
>  {
>     if (oldMap == newMap)
>        return;
>  
>     Cache.ReMap(false);
>  
> -   CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap;
> +   CurrentFile = RebasePointer(CurrentFile, oldMap, newMap);
>  
>     for (size_t i = 0; i < _count(UniqHash); ++i)
>        if (UniqHash[i] != 0)
> -         UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap;
> +         UniqHash[i] = RebasePointer(UniqHash[i], oldMap, newMap);
>  
>     for (auto i = Dynamic<pkgCache::PkgIterator>::toReMap.begin();
>          i != Dynamic<pkgCache::PkgIterator>::toReMap.end(); ++i)
> @@ -147,7 +148,7 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
>  // CacheGenerator::WriteStringInMap					/*{{{*/
>  std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(const char *String,
>  					unsigned long Len) {
> -   void const * const oldMap = Map.Data();
> +   void *oldMap = Map.Data();
>     const auto index = Map.WriteString(String, Len);
>     if (index)
>        ReMap(oldMap, Map.Data());
> @@ -156,7 +157,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(cons
>  									/*}}}*/
>  // CacheGenerator::WriteStringInMap					/*{{{*/
>  std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(const char *String) {
> -   void const * const oldMap = Map.Data();
> +   void *oldMap = Map.Data();
>     const auto index = Map.WriteString(String);
>     if (index)
>        ReMap(oldMap, Map.Data());
> @@ -164,7 +165,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(cons
>  }
>  									/*}}}*/
>  std::experimental::optional<map_ptrloc> pkgCacheGenerator::AllocateInMap(unsigned long size) {/*{{{*/
> -   void const * const oldMap = Map.Data();
> +   void *oldMap = Map.Data();
>     const auto index = Map.Allocate(size);
>     if (index)
>        ReMap(oldMap, Map.Data());
> @@ -229,7 +230,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>        pkgCache::VerIterator Ver = Pkg.VersionList();
>        Dynamic<pkgCache::VerIterator> DynVer(Ver);
>        map_ptrloc *Last = &Pkg->VersionList;
> -      const void * oldMap = Map.Data();
> +      void *oldMap = Map.Data();
>        int Res = 1;
>        for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
>        {
> @@ -271,7 +272,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>  
>        if (oldMap != Map.Data())
>        {
> -         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
> +         Last = RebasePointer(Last, oldMap, Map.Data());
>           oldMap = Map.Data();
>        }
>  
> @@ -297,7 +298,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>                                PackageName.c_str(), 1);
>  
>        if (oldMap != Map.Data())
> -         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
> +         Last = RebasePointer(Last, oldMap, Map.Data());
>        *Last = *verindex;
>  
>        Ver->ParentPkg = Pkg.Index();
> @@ -553,7 +554,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
>  					       unsigned int Op,
>  					       unsigned int Type)
>  {
> -   void const * const oldMap = Owner->Map.Data();
> +   void *oldMap = Owner->Map.Data();
>     pkgCache &Cache = Owner->Cache;
>     
>     // Get a structure
> @@ -605,7 +606,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
>  	 OldDepLast = &D->NextDepends;
>        OldDepVer = Ver;
>     } else if (oldMap != Owner->Map.Data())
> -      OldDepLast += (map_ptrloc*) Owner->Map.Data() - (map_ptrloc*) oldMap;
> +      OldDepLast = RebasePointer(OldDepLast, oldMap, Owner->Map.Data());
>  
>     // Is it a file dependency?
>     if (PackageName[0] == '/')
> @@ -739,7 +740,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
>     }
>     
>     // Get a structure
> -   void const * const oldMap = Map.Data();
> +   void *oldMap = Map.Data();
>     const auto Item = AllocateInMap(sizeof(pkgCache::StringItem));
>     const auto idxString = WriteStringInMap(S, Size);
>     if ((!Item) || (!idxString))
> @@ -747,8 +748,8 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
>  
>     if (oldMap != Map.Data())
>     {
> -      Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
> -      I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap;
> +      Last = RebasePointer(Last, oldMap, Map.Data());
> +      I = RebasePointer(I, oldMap, Map.Data());
>     }
>  
>     *Last = *Item;
> diff --git a/apt/apt-pkg/pkgcachegen.h b/apt/apt-pkg/pkgcachegen.h
> index 77075a6..0faf6e1 100644
> --- a/apt/apt-pkg/pkgcachegen.h
> +++ b/apt/apt-pkg/pkgcachegen.h
> @@ -72,7 +72,7 @@ class pkgCacheGenerator
>     class DynamicFunction
>     {
>     public:
> -      typedef std::function<void(const void *, const void *)> function;
> +      typedef std::function<void(void *, void *)> function;
>  
>        static std::set<DynamicFunction*> toReMap;
>  
> @@ -93,7 +93,7 @@ class pkgCacheGenerator
>           toReMap.erase(this);
>        }
>  
> -      void call(const void *oldMap, const void *newMap)
> +      void call(void *oldMap, void *newMap)
>        {
>           if (m_function)
>              m_function(oldMap, newMap);
> @@ -140,7 +140,7 @@ class pkgCacheGenerator
>     // CNC:2003-03-18
>     inline void ResetFileDeps() {FoundFileDeps = false;};
>  
> -   void ReMap(void const * const oldMap, void const * const newMap);
> +   void ReMap(void *oldMap, void *newMap);
>  
>     pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress);
>     ~pkgCacheGenerator();
> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
> new file mode 100644
> index 0000000..f6b3c15
> --- /dev/null
> +++ b/apt/apt-pkg/rebase_pointer.h
> @@ -0,0 +1,16 @@
> +#ifndef PKGLIB_REBASE_POINTER_H
> +#define PKGLIB_REBASE_POINTER_H
> +
> +template <typename T>
> +static inline T* RebasePointer(T *ptr, void *old_base, void *new_base)
> +{
> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(old_base)));
> +}
> +
> +template <typename T>
> +static inline const T* RebasePointer(const T *ptr, void *old_base, void *new_base)
> +{
> +   return reinterpret_cast<const T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<const char*>(ptr) - reinterpret_cast<char*>(old_base)));
> +}
> +
> +#endif
> diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc b/apt/apt-pkg/rpm/rpmlistparser.cc
> index 9b2e9ad..bd13b99 100644
> --- a/apt/apt-pkg/rpm/rpmlistparser.cc
> +++ b/apt/apt-pkg/rpm/rpmlistparser.cc
> @@ -25,6 +25,7 @@
>  #include <apt-pkg/strutl.h>
>  #include <apt-pkg/crc-16.h>
>  #include <apt-pkg/tagfile.h>
> +#include <apt-pkg/rebase_pointer.h>
>  
>  #include <apti18n.h>
>  
> @@ -50,13 +51,13 @@ rpmListParser::rpmListParser(RPMHandler *Handler)
>     {
>        SeenPackages.reset(new SeenPackagesType);
>        m_SeenPackagesRealloc.reset(new pkgCacheGenerator::DynamicFunction(
> -         [this] (void const *oldMap, void const *newMap)
> +         [this] (void *oldMap, void *newMap)
>        {
>           SeenPackagesType tmp;
>  
>           for (auto iter: *SeenPackages)
>           {
> -            tmp.insert(iter + (static_cast<const char *>(newMap) - static_cast<const char *>(oldMap)));
> +            tmp.insert(RebasePointer(iter, oldMap, newMap));
>           }
>  
>           SeenPackages->swap(tmp);
> diff --git a/apt/apt-pkg/rpm/rpmpackagedata.cc b/apt/apt-pkg/rpm/rpmpackagedata.cc
> index 61c15d5..d6c677b 100644
> --- a/apt/apt-pkg/rpm/rpmpackagedata.cc
> +++ b/apt/apt-pkg/rpm/rpmpackagedata.cc
> @@ -23,7 +23,7 @@ RPMPackageData::RPMPackageData()
>  #endif
>  {
>     m_VerMapRealloc.reset(new pkgCacheGenerator::DynamicFunction(
> -      [this] (void const *oldMap, void const *newMap)
> +      [this] (void *oldMap, void *newMap)
>     {
>        for (auto iter1 = VerMap.begin(); iter1 != VerMap.end(); ++iter1)
>        {


Best regards,
Andrew Savchenko

[-- Attachment #2: Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 1/2] Add option for debugging DynamicMMap::Allocate
  2019-12-06 13:16 [devel] [PATCH for apt 1/2] Add option for debugging DynamicMMap::Allocate Aleksei Nikiforov
  2019-12-06 13:16 ` [devel] [PATCH for apt 2/2] Fix pointer arithmetics Aleksei Nikiforov
@ 2019-12-08 22:50 ` Dmitry V. Levin
  2019-12-09  6:58   ` Aleksei Nikiforov
  2019-12-09  7:00   ` [devel] [PATCH for apt 1/2 v2] Add option for debugging Debug::DynamicMMap::Allocate Aleksei Nikiforov
  1 sibling, 2 replies; 34+ messages in thread
From: Dmitry V. Levin @ 2019-12-08 22:50 UTC (permalink / raw)
  To: Aleksei Nikiforov; +Cc: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 2978 bytes --]

On Fri, Dec 06, 2019 at 04:16:05PM +0300, Aleksei Nikiforov wrote:
> ---
>  apt/apt-pkg/contrib/mmap.cc | 15 +++++++++++++++
>  apt/doc/apt.conf.5.sgml     |  2 +-
>  2 files changed, 16 insertions(+), 1 deletion(-)

I suggest adding the name of the new option to the commit message
so it would be git-grep'able, for example:

Add Debug::DynamicMMap::Allocate option

Add a new option for debugging DynamicMMap::Allocate.

> diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
> index a3b06cc..cf01be9 100644
> --- a/apt/apt-pkg/contrib/mmap.cc
> +++ b/apt/apt-pkg/contrib/mmap.cc
> @@ -265,6 +265,21 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
>     // No pool is allocated, use an unallocated one
>     if (I == Pools + PoolCount)
>     {
> +      static const bool debug_grow = _config->FindB("Debug::DynamicMMap::Allocate", false);
> +
> +      if (debug_grow)
> +      {
> +         Pool *pool_iter = Pools;
> +         size_t pool_idx = 0;
> +
> +         _error->Warning(_("DynamicMMap::Allocate: allocating item of size %lu"), ItemSize);
> +
> +         for (; pool_idx < PoolCount; ++pool_iter, ++pool_idx)
> +         {
> +            _error->Warning(_("DynamicMMap::Allocate: Pool %zu, item size: %lu, start: %lu, count: %lu"), pool_idx, pool_iter->ItemSize, pool_iter->Start, pool_iter->Count);
> +         }
> +      }

Nitpicking:
- this is debugging, there is no need to optimize, so there is no need for
  pool_iter;
- let's use "for" loop initial declarations, they are widely used in apt
  already;
- the type of iterator should be the same as the type of PoolCount;
- lines are too long.

Consider something like this (untested):

      if (debug_grow) {
         _error->Warning(_("DynamicMMap::Allocate: allocating item of size %lu"),
                         ItemSize);

         for (unsigned int i = 0; i < PoolCount; ++i) {
            _error->Warning(_("DynamicMMap::Allocate: Pool %u, item size: %lu"
                              ", start: %lu, count: %lu"),
                            i, Pools[i].ItemSize,
                            Pools[i].Start, Pools[i].Count);
         }
      }

>        // Woops, we ran out, the calling code should allocate more.
>        if (Empty == 0)
>        {
> diff --git a/apt/doc/apt.conf.5.sgml b/apt/doc/apt.conf.5.sgml
> index 0a72e45..72fc0c3 100644
> --- a/apt/doc/apt.conf.5.sgml
> +++ b/apt/doc/apt.conf.5.sgml
> @@ -526,7 +526,7 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
>     disable the inclusion of statfs data in CDROM IDs.
>     </para><para>
>     To debug issues related to dynamic memory allocation, an option
> -   <literal/Debug::DynamicMMap::Grow/ may be used.
> +   <literal/Debug::DynamicMMap::Grow/ and <literal/Debug::DynamicMMap::Allocate/ may be used.

As we've got two options now, I suggest s/an option/options/ .


-- 
ldv

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-07 14:52       ` Andrey Savchenko
@ 2019-12-08 22:56         ` Dmitry V. Levin
  2019-12-09  6:54         ` Aleksei Nikiforov
  1 sibling, 0 replies; 34+ messages in thread
From: Dmitry V. Levin @ 2019-12-08 22:56 UTC (permalink / raw)
  To: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 912 bytes --]

On Sat, Dec 07, 2019 at 05:52:01PM +0300, Andrey Savchenko wrote:
> Hi all!
> 
> On Fri,  6 Dec 2019 18:36:55 +0300 Aleksei Nikiforov wrote:
> > This change should fix pointer arithmetic issues for e2k.
> 
> This commit message is misleading. Pointer arithmetic is broken on
> all architectures, but by pure chance in happens to work correctly
> when gcc is used. On e2k the lcc compiler is used, so problem
> manifests itself. But this doesn't change the fact that pointer
> arithmetic was flawed on all architectures.

Strictly speaking, it's not "broken", it's "UB", but I agree
it is not specific to e2k.

My original commit message for this change was the following:

"Fix UB in pointer arithmetic

Commit 6d5e6a689d07de8feef2cbecb24bc42d5994861b aka 0.5.15lorg2-alt70~9
among other changes introduced UB in pointer arithmetic by casting raw
pointers to specific types."


-- 
ldv

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-06 15:36     ` [devel] [PATCH for apt 2/2 v2] " Aleksei Nikiforov
  2019-12-07 14:52       ` Andrey Savchenko
@ 2019-12-08 23:21       ` Dmitry V. Levin
  2019-12-09  7:08         ` Aleksei Nikiforov
  1 sibling, 1 reply; 34+ messages in thread
From: Dmitry V. Levin @ 2019-12-08 23:21 UTC (permalink / raw)
  To: Aleksei Nikiforov; +Cc: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 2012 bytes --]

On Fri, Dec 06, 2019 at 06:36:55PM +0300, Aleksei Nikiforov wrote:
[...]
> @@ -85,11 +87,11 @@ class pkgCache::PkgIterator
>     inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
>     OkState State() const;
>  
> -   void ReMap(void const * const oldMap, void const * const newMap)
> +   void ReMap(void *oldMap, void *newMap)

Is there any particular reason for stripping const here and in other
similar places?

[...]
> @@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
>        Pool* oldPools = Pools;
>        auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
>        if (Pools != oldPools)
> -         I += Pools - oldPools;
> +         I = RebasePointer(I, oldPools, Pools);
>  
>        // Does the allocation failed ?
>        if (!idxResult)

In my patch RebasePointer invocation was after the idxResult check,
not before the check.

By the way, in this and other similar cases,
is there any reason for "Pools != oldPools" check?
Is RebasePointer incapable of handling this, or is it an optimization?

[...]
> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
> new file mode 100644
> index 0000000..f6b3c15
> --- /dev/null
> +++ b/apt/apt-pkg/rebase_pointer.h
> @@ -0,0 +1,16 @@
> +#ifndef PKGLIB_REBASE_POINTER_H
> +#define PKGLIB_REBASE_POINTER_H
> +
> +template <typename T>
> +static inline T* RebasePointer(T *ptr, void *old_base, void *new_base)
> +{
> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(old_base)));
> +}
> +
> +template <typename T>
> +static inline const T* RebasePointer(const T *ptr, void *old_base, void *new_base)
> +{
> +   return reinterpret_cast<const T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<const char*>(ptr) - reinterpret_cast<char*>(old_base)));
> +}
> +
> +#endif

Do we really need two templates here?


-- 
ldv

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2] Fix pointer arithmetics
  2019-12-06 13:16 ` [devel] [PATCH for apt 2/2] Fix pointer arithmetics Aleksei Nikiforov
  2019-12-06 13:36   ` Ivan A. Melnikov
@ 2019-12-08 23:31   ` Dmitry V. Levin
  2019-12-09  7:09     ` Aleksei Nikiforov
  2019-12-09  7:16     ` [devel] [PATCH for apt 2/2 v3] " Aleksei Nikiforov
  2019-12-09 23:54   ` [devel] [PATCH apt 0/3] Fix 0.5.15lorg2-alt70~9 fallout Dmitry V. Levin
  2 siblings, 2 replies; 34+ messages in thread
From: Dmitry V. Levin @ 2019-12-08 23:31 UTC (permalink / raw)
  To: Aleksei Nikiforov; +Cc: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 1215 bytes --]

On Fri, Dec 06, 2019 at 04:16:06PM +0300, Aleksei Nikiforov wrote:
[...]
> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
> new file mode 100644
> index 0000000..efc4074
> --- /dev/null
> +++ b/apt/apt-pkg/rebase_pointer.h
> @@ -0,0 +1,16 @@
> +#ifndef PKGLIB_REBASE_POINTER_H
> +#define PKGLIB_REBASE_POINTER_H
> +
> +template <typename T>
> +static inline T* RebasePointer(T *ptr, const void * const old_base, const void * const new_base)
> +{
> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(ptr) + (reinterpret_cast<char const * const>(new_base) - reinterpret_cast<char const * const>(old_base)));
> +}
> +
> +template <typename T>
> +static inline const T* RebasePointer(const T *ptr, const void * const old_base, const void * const new_base)
> +{
> +   return reinterpret_cast<const T*>(reinterpret_cast<const char*>(ptr) + (reinterpret_cast<char const * const>(new_base) - reinterpret_cast<char const * const>(old_base)));

This line is way too long - about twice longer than a normal line of code.
Please break long lines.

My edition of rebase_pointer.h had the maximum length of all lines within
the traditional 80-symbol limit.


-- 
ldv

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-07 14:52       ` Andrey Savchenko
  2019-12-08 22:56         ` Dmitry V. Levin
@ 2019-12-09  6:54         ` Aleksei Nikiforov
  2019-12-12 19:20           ` Andrey Savchenko
  1 sibling, 1 reply; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-09  6:54 UTC (permalink / raw)
  To: devel

07.12.2019 17:52, Andrey Savchenko пишет:
> Hi all!
> 
> On Fri,  6 Dec 2019 18:36:55 +0300 Aleksei Nikiforov wrote:
>> This change should fix pointer arithmetic issues for e2k.
> 
> This commit message is misleading. Pointer arithmetic is broken on
> all architectures, but by pure chance in happens to work correctly
> when gcc is used. On e2k the lcc compiler is used, so problem
> manifests itself. But this doesn't change the fact that pointer
> arithmetic was flawed on all architectures.
> 

Your first sentence contradicts later ones. You just repeated my 
sentence about issue manifesting on e2k, but you did it more verbosely. 
Yes, there is a flaw for all architectures, but it manifests only for 
e2k in practice, thus change fixes it for e2k. So, what's misleading there?

>> ---
>>   apt/apt-pkg/Makefile.am           |  1 +
>>   apt/apt-pkg/cacheiterators.h      | 26 ++++++++++++++------------
>>   apt/apt-pkg/contrib/mmap.cc       |  8 +++++---
>>   apt/apt-pkg/pkgcachegen.cc        | 29 +++++++++++++++--------------
>>   apt/apt-pkg/pkgcachegen.h         |  6 +++---
>>   apt/apt-pkg/rebase_pointer.h      | 16 ++++++++++++++++
>>   apt/apt-pkg/rpm/rpmlistparser.cc  |  5 +++--
>>   apt/apt-pkg/rpm/rpmpackagedata.cc |  2 +-
>>   8 files changed, 58 insertions(+), 35 deletions(-)
>>   create mode 100644 apt/apt-pkg/rebase_pointer.h
>>
>> diff --git a/apt/apt-pkg/Makefile.am b/apt/apt-pkg/Makefile.am
>> index 4c0d234..d038d01 100644
>> --- a/apt/apt-pkg/Makefile.am
>> +++ b/apt/apt-pkg/Makefile.am
>> @@ -94,6 +94,7 @@ libapt_pkg_la_SOURCES = \
>>   	pkgsystem.h \
>>   	policy.cc \
>>   	policy.h \
>> +	rebase_pointer.h \
>>   	repository.cc \
>>   	repository.h \
>>   	scopeexit.h \
>> diff --git a/apt/apt-pkg/cacheiterators.h b/apt/apt-pkg/cacheiterators.h
>> index a4bf670..118838e 100644
>> --- a/apt/apt-pkg/cacheiterators.h
>> +++ b/apt/apt-pkg/cacheiterators.h
>> @@ -34,6 +34,8 @@
>>   #pragma interface "apt-pkg/cacheiterators.h"
>>   #endif
>>   
>> +#include <apt-pkg/rebase_pointer.h>
>> +
>>   #include <set>
>>   
>>   // Package Iterator
>> @@ -85,11 +87,11 @@ class pkgCache::PkgIterator
>>      inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
>>      OkState State() const;
>>   
>> -   void ReMap(void const * const oldMap, void const * const newMap)
>> +   void ReMap(void *oldMap, void *newMap)
>>      {
>>         if (Owner == 0 || Pkg == 0)
>>            return;
>> -      Pkg += static_cast<Package const *>(newMap) - static_cast<Package const *>(oldMap);
>> +      Pkg = RebasePointer(Pkg, oldMap, newMap);
>>      }
>>   
>>      // Constructors
>> @@ -147,11 +149,11 @@ class pkgCache::VerIterator
>>      bool Automatic() const;
>>      VerFileIterator NewestFile() const;
>>   
>> -   void ReMap(void const * const oldMap, void const * const newMap)
>> +   void ReMap(void *oldMap, void *newMap)
>>      {
>>         if (Owner == 0 || Ver == 0)
>>            return;
>> -      Ver += static_cast<Version const *>(newMap) - static_cast<Version const *>(oldMap);
>> +      Ver = RebasePointer(Ver, oldMap, newMap);
>>      }
>>   
>>      inline VerIterator() : Ver(0), Owner(0) {};
>> @@ -220,11 +222,11 @@ class pkgCache::DepIterator
>>      inline const char *CompType() {return Owner->CompType(Dep->CompareOp);};
>>      inline const char *DepType() {return Owner->DepType(Dep->Type);};
>>   
>> -   void ReMap(void const * const oldMap, void const * const newMap)
>> +   void ReMap(void *oldMap, void *newMap)
>>      {
>>         if (Owner == 0 || Dep == 0)
>>            return;
>> -      Dep += static_cast<Dependency const *>(newMap) - static_cast<Dependency const *>(oldMap);
>> +      Dep = RebasePointer(Dep, oldMap, newMap);
>>      }
>>   
>>      inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) :
>> @@ -279,11 +281,11 @@ class pkgCache::PrvIterator
>>      inline PkgIterator OwnerPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[Prv->Version].ParentPkg);};
>>      inline unsigned long long Index() const {return Prv - Owner->ProvideP;};
>>   
>> -   void ReMap(void const * const oldMap, void const * const newMap)
>> +   void ReMap(void *oldMap, void *newMap)
>>      {
>>         if (Owner == 0 || Prv == 0)
>>            return;
>> -      Prv += static_cast<Provides const *>(newMap) - static_cast<Provides const *>(oldMap);
>> +      Prv = RebasePointer(Prv, oldMap, newMap);
>>      }
>>   
>>      inline PrvIterator() : Prv(0), Type(PrvVer), Owner(0)  {};
>> @@ -342,11 +344,11 @@ class pkgCache::PkgFileIterator
>>      bool IsOk();
>>      string RelStr();
>>   
>> -   void ReMap(void const * const oldMap, void const * const newMap)
>> +   void ReMap(void *oldMap, void *newMap)
>>      {
>>         if (Owner == 0 || File == 0)
>>            return;
>> -      File += static_cast<PackageFile const *>(newMap) - static_cast<PackageFile const *>(oldMap);
>> +      File = RebasePointer(File, oldMap, newMap);
>>      }
>>   
>>      // Constructors
>> @@ -383,11 +385,11 @@ class pkgCache::VerFileIterator
>>      inline PkgFileIterator File() const {return PkgFileIterator(*Owner,FileP->File + Owner->PkgFileP);};
>>      inline unsigned long long Index() const {return FileP - Owner->VerFileP;};
>>   
>> -   void ReMap(void const * const oldMap, void const * const newMap)
>> +   void ReMap(void *oldMap, void *newMap)
>>      {
>>         if (Owner == 0 || FileP == 0)
>>            return;
>> -      FileP += static_cast<VerFile const *>(newMap) - static_cast<VerFile const *>(oldMap);
>> +      FileP = RebasePointer(FileP, oldMap, newMap);
>>      }
>>   
>>      inline VerFileIterator() : Owner(0), FileP(0) {};
>> diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
>> index cf01be9..35f1a25 100644
>> --- a/apt/apt-pkg/contrib/mmap.cc
>> +++ b/apt/apt-pkg/contrib/mmap.cc
>> @@ -30,6 +30,7 @@
>>   #include <apt-pkg/configuration.h>
>>   #include <apt-pkg/mmap.h>
>>   #include <apt-pkg/error.h>
>> +#include <apt-pkg/rebase_pointer.h>
>>   
>>   #include <apti18n.h>
>>   
>> @@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
>>         Pool* oldPools = Pools;
>>         auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
>>         if (Pools != oldPools)
>> -         I += Pools - oldPools;
>> +         I = RebasePointer(I, oldPools, Pools);
>>   
>>         // Does the allocation failed ?
>>         if (!idxResult)
>> @@ -371,7 +372,7 @@ bool DynamicMMap::Grow(unsigned long long size)
>>         Fd->Write(&C,sizeof(C));
>>      }
>>   
>> -   unsigned long const poolOffset = Pools - ((Pool*) Base);
>> +   void *old_base = Base;
>>   
>>      if (Fd != 0)
>>      {
>> @@ -408,7 +409,8 @@ bool DynamicMMap::Grow(unsigned long long size)
>>         memset((char*)Base + WorkSpace, 0, newSize - WorkSpace);
>>      }
>>   
>> -   Pools = (Pool*) Base + poolOffset;
>> +   if (Base != old_base)
>> +      Pools = RebasePointer(Pools, old_base, Base);
>>      WorkSpace = newSize;
>>   
>>      return true;
>> diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc
>> index 654c81c..37364e9 100644
>> --- a/apt/apt-pkg/pkgcachegen.cc
>> +++ b/apt/apt-pkg/pkgcachegen.cc
>> @@ -26,6 +26,7 @@
>>   #include <apt-pkg/strutl.h>
>>   #include <apt-pkg/sptr.h>
>>   #include <apt-pkg/pkgsystem.h>
>> +#include <apt-pkg/rebase_pointer.h>
>>   
>>   #include <apti18n.h>
>>   
>> @@ -109,18 +110,18 @@ pkgCacheGenerator::~pkgCacheGenerator()
>>      Map.Sync(0,sizeof(pkgCache::Header));
>>   }
>>   									/*}}}*/
>> -void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newMap)
>> +void pkgCacheGenerator::ReMap(void *oldMap, void *newMap)
>>   {
>>      if (oldMap == newMap)
>>         return;
>>   
>>      Cache.ReMap(false);
>>   
>> -   CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap;
>> +   CurrentFile = RebasePointer(CurrentFile, oldMap, newMap);
>>   
>>      for (size_t i = 0; i < _count(UniqHash); ++i)
>>         if (UniqHash[i] != 0)
>> -         UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap;
>> +         UniqHash[i] = RebasePointer(UniqHash[i], oldMap, newMap);
>>   
>>      for (auto i = Dynamic<pkgCache::PkgIterator>::toReMap.begin();
>>           i != Dynamic<pkgCache::PkgIterator>::toReMap.end(); ++i)
>> @@ -147,7 +148,7 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
>>   // CacheGenerator::WriteStringInMap					/*{{{*/
>>   std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(const char *String,
>>   					unsigned long Len) {
>> -   void const * const oldMap = Map.Data();
>> +   void *oldMap = Map.Data();
>>      const auto index = Map.WriteString(String, Len);
>>      if (index)
>>         ReMap(oldMap, Map.Data());
>> @@ -156,7 +157,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(cons
>>   									/*}}}*/
>>   // CacheGenerator::WriteStringInMap					/*{{{*/
>>   std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(const char *String) {
>> -   void const * const oldMap = Map.Data();
>> +   void *oldMap = Map.Data();
>>      const auto index = Map.WriteString(String);
>>      if (index)
>>         ReMap(oldMap, Map.Data());
>> @@ -164,7 +165,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(cons
>>   }
>>   									/*}}}*/
>>   std::experimental::optional<map_ptrloc> pkgCacheGenerator::AllocateInMap(unsigned long size) {/*{{{*/
>> -   void const * const oldMap = Map.Data();
>> +   void *oldMap = Map.Data();
>>      const auto index = Map.Allocate(size);
>>      if (index)
>>         ReMap(oldMap, Map.Data());
>> @@ -229,7 +230,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>>         pkgCache::VerIterator Ver = Pkg.VersionList();
>>         Dynamic<pkgCache::VerIterator> DynVer(Ver);
>>         map_ptrloc *Last = &Pkg->VersionList;
>> -      const void * oldMap = Map.Data();
>> +      void *oldMap = Map.Data();
>>         int Res = 1;
>>         for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
>>         {
>> @@ -271,7 +272,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>>   
>>         if (oldMap != Map.Data())
>>         {
>> -         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
>> +         Last = RebasePointer(Last, oldMap, Map.Data());
>>            oldMap = Map.Data();
>>         }
>>   
>> @@ -297,7 +298,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>>                                 PackageName.c_str(), 1);
>>   
>>         if (oldMap != Map.Data())
>> -         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
>> +         Last = RebasePointer(Last, oldMap, Map.Data());
>>         *Last = *verindex;
>>   
>>         Ver->ParentPkg = Pkg.Index();
>> @@ -553,7 +554,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
>>   					       unsigned int Op,
>>   					       unsigned int Type)
>>   {
>> -   void const * const oldMap = Owner->Map.Data();
>> +   void *oldMap = Owner->Map.Data();
>>      pkgCache &Cache = Owner->Cache;
>>      
>>      // Get a structure
>> @@ -605,7 +606,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
>>   	 OldDepLast = &D->NextDepends;
>>         OldDepVer = Ver;
>>      } else if (oldMap != Owner->Map.Data())
>> -      OldDepLast += (map_ptrloc*) Owner->Map.Data() - (map_ptrloc*) oldMap;
>> +      OldDepLast = RebasePointer(OldDepLast, oldMap, Owner->Map.Data());
>>   
>>      // Is it a file dependency?
>>      if (PackageName[0] == '/')
>> @@ -739,7 +740,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
>>      }
>>      
>>      // Get a structure
>> -   void const * const oldMap = Map.Data();
>> +   void *oldMap = Map.Data();
>>      const auto Item = AllocateInMap(sizeof(pkgCache::StringItem));
>>      const auto idxString = WriteStringInMap(S, Size);
>>      if ((!Item) || (!idxString))
>> @@ -747,8 +748,8 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
>>   
>>      if (oldMap != Map.Data())
>>      {
>> -      Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
>> -      I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap;
>> +      Last = RebasePointer(Last, oldMap, Map.Data());
>> +      I = RebasePointer(I, oldMap, Map.Data());
>>      }
>>   
>>      *Last = *Item;
>> diff --git a/apt/apt-pkg/pkgcachegen.h b/apt/apt-pkg/pkgcachegen.h
>> index 77075a6..0faf6e1 100644
>> --- a/apt/apt-pkg/pkgcachegen.h
>> +++ b/apt/apt-pkg/pkgcachegen.h
>> @@ -72,7 +72,7 @@ class pkgCacheGenerator
>>      class DynamicFunction
>>      {
>>      public:
>> -      typedef std::function<void(const void *, const void *)> function;
>> +      typedef std::function<void(void *, void *)> function;
>>   
>>         static std::set<DynamicFunction*> toReMap;
>>   
>> @@ -93,7 +93,7 @@ class pkgCacheGenerator
>>            toReMap.erase(this);
>>         }
>>   
>> -      void call(const void *oldMap, const void *newMap)
>> +      void call(void *oldMap, void *newMap)
>>         {
>>            if (m_function)
>>               m_function(oldMap, newMap);
>> @@ -140,7 +140,7 @@ class pkgCacheGenerator
>>      // CNC:2003-03-18
>>      inline void ResetFileDeps() {FoundFileDeps = false;};
>>   
>> -   void ReMap(void const * const oldMap, void const * const newMap);
>> +   void ReMap(void *oldMap, void *newMap);
>>   
>>      pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress);
>>      ~pkgCacheGenerator();
>> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
>> new file mode 100644
>> index 0000000..f6b3c15
>> --- /dev/null
>> +++ b/apt/apt-pkg/rebase_pointer.h
>> @@ -0,0 +1,16 @@
>> +#ifndef PKGLIB_REBASE_POINTER_H
>> +#define PKGLIB_REBASE_POINTER_H
>> +
>> +template <typename T>
>> +static inline T* RebasePointer(T *ptr, void *old_base, void *new_base)
>> +{
>> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(old_base)));
>> +}
>> +
>> +template <typename T>
>> +static inline const T* RebasePointer(const T *ptr, void *old_base, void *new_base)
>> +{
>> +   return reinterpret_cast<const T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<const char*>(ptr) - reinterpret_cast<char*>(old_base)));
>> +}
>> +
>> +#endif
>> diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc b/apt/apt-pkg/rpm/rpmlistparser.cc
>> index 9b2e9ad..bd13b99 100644
>> --- a/apt/apt-pkg/rpm/rpmlistparser.cc
>> +++ b/apt/apt-pkg/rpm/rpmlistparser.cc
>> @@ -25,6 +25,7 @@
>>   #include <apt-pkg/strutl.h>
>>   #include <apt-pkg/crc-16.h>
>>   #include <apt-pkg/tagfile.h>
>> +#include <apt-pkg/rebase_pointer.h>
>>   
>>   #include <apti18n.h>
>>   
>> @@ -50,13 +51,13 @@ rpmListParser::rpmListParser(RPMHandler *Handler)
>>      {
>>         SeenPackages.reset(new SeenPackagesType);
>>         m_SeenPackagesRealloc.reset(new pkgCacheGenerator::DynamicFunction(
>> -         [this] (void const *oldMap, void const *newMap)
>> +         [this] (void *oldMap, void *newMap)
>>         {
>>            SeenPackagesType tmp;
>>   
>>            for (auto iter: *SeenPackages)
>>            {
>> -            tmp.insert(iter + (static_cast<const char *>(newMap) - static_cast<const char *>(oldMap)));
>> +            tmp.insert(RebasePointer(iter, oldMap, newMap));
>>            }
>>   
>>            SeenPackages->swap(tmp);
>> diff --git a/apt/apt-pkg/rpm/rpmpackagedata.cc b/apt/apt-pkg/rpm/rpmpackagedata.cc
>> index 61c15d5..d6c677b 100644
>> --- a/apt/apt-pkg/rpm/rpmpackagedata.cc
>> +++ b/apt/apt-pkg/rpm/rpmpackagedata.cc
>> @@ -23,7 +23,7 @@ RPMPackageData::RPMPackageData()
>>   #endif
>>   {
>>      m_VerMapRealloc.reset(new pkgCacheGenerator::DynamicFunction(
>> -      [this] (void const *oldMap, void const *newMap)
>> +      [this] (void *oldMap, void *newMap)
>>      {
>>         for (auto iter1 = VerMap.begin(); iter1 != VerMap.end(); ++iter1)
>>         {
> 
> 
> Best regards,
> Andrew Savchenko
> 
> 
> _______________________________________________
> Devel mailing list
> Devel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel
> 


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 1/2] Add option for debugging DynamicMMap::Allocate
  2019-12-08 22:50 ` [devel] [PATCH for apt 1/2] Add option for debugging DynamicMMap::Allocate Dmitry V. Levin
@ 2019-12-09  6:58   ` Aleksei Nikiforov
  2019-12-09 10:24     ` Dmitry V. Levin
  2019-12-09  7:00   ` [devel] [PATCH for apt 1/2 v2] Add option for debugging Debug::DynamicMMap::Allocate Aleksei Nikiforov
  1 sibling, 1 reply; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-09  6:58 UTC (permalink / raw)
  To: devel

09.12.2019 1:50, Dmitry V. Levin пишет:
> On Fri, Dec 06, 2019 at 04:16:05PM +0300, Aleksei Nikiforov wrote:
>> ---
>>   apt/apt-pkg/contrib/mmap.cc | 15 +++++++++++++++
>>   apt/doc/apt.conf.5.sgml     |  2 +-
>>   2 files changed, 16 insertions(+), 1 deletion(-)
> 
> I suggest adding the name of the new option to the commit message
> so it would be git-grep'able, for example:
> 
> Add Debug::DynamicMMap::Allocate option
> 
> Add a new option for debugging DynamicMMap::Allocate.
> 

But option name is already in commit message. See the email subject 
which is also a part of commit message. Why is it needed to duplicate it?

I'll update option name in subject to completely match full option name.

>> diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
>> index a3b06cc..cf01be9 100644
>> --- a/apt/apt-pkg/contrib/mmap.cc
>> +++ b/apt/apt-pkg/contrib/mmap.cc
>> @@ -265,6 +265,21 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
>>      // No pool is allocated, use an unallocated one
>>      if (I == Pools + PoolCount)
>>      {
>> +      static const bool debug_grow = _config->FindB("Debug::DynamicMMap::Allocate", false);
>> +
>> +      if (debug_grow)
>> +      {
>> +         Pool *pool_iter = Pools;
>> +         size_t pool_idx = 0;
>> +
>> +         _error->Warning(_("DynamicMMap::Allocate: allocating item of size %lu"), ItemSize);
>> +
>> +         for (; pool_idx < PoolCount; ++pool_iter, ++pool_idx)
>> +         {
>> +            _error->Warning(_("DynamicMMap::Allocate: Pool %zu, item size: %lu, start: %lu, count: %lu"), pool_idx, pool_iter->ItemSize, pool_iter->Start, pool_iter->Count);
>> +         }
>> +      }
> 
> Nitpicking:
> - this is debugging, there is no need to optimize, so there is no need for
>    pool_iter;
> - let's use "for" loop initial declarations, they are widely used in apt
>    already;
> - the type of iterator should be the same as the type of PoolCount;
> - lines are too long.
> 
> Consider something like this (untested):
> 
>        if (debug_grow) {
>           _error->Warning(_("DynamicMMap::Allocate: allocating item of size %lu"),
>                           ItemSize);
> 
>           for (unsigned int i = 0; i < PoolCount; ++i) {
>              _error->Warning(_("DynamicMMap::Allocate: Pool %u, item size: %lu"
>                                ", start: %lu, count: %lu"),
>                              i, Pools[i].ItemSize,
>                              Pools[i].Start, Pools[i].Count);
>           }
>        }
> 
>>         // Woops, we ran out, the calling code should allocate more.
>>         if (Empty == 0)
>>         {
>> diff --git a/apt/doc/apt.conf.5.sgml b/apt/doc/apt.conf.5.sgml
>> index 0a72e45..72fc0c3 100644
>> --- a/apt/doc/apt.conf.5.sgml
>> +++ b/apt/doc/apt.conf.5.sgml
>> @@ -526,7 +526,7 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
>>      disable the inclusion of statfs data in CDROM IDs.
>>      </para><para>
>>      To debug issues related to dynamic memory allocation, an option
>> -   <literal/Debug::DynamicMMap::Grow/ may be used.
>> +   <literal/Debug::DynamicMMap::Grow/ and <literal/Debug::DynamicMMap::Allocate/ may be used.
> 
> As we've got two options now, I suggest s/an option/options/ .
> 
> 

Thanks, I'll update this text.

> 
> _______________________________________________
> Devel mailing list
> Devel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel
> 


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [devel] [PATCH for apt 1/2 v2] Add option for debugging Debug::DynamicMMap::Allocate
  2019-12-08 22:50 ` [devel] [PATCH for apt 1/2] Add option for debugging DynamicMMap::Allocate Dmitry V. Levin
  2019-12-09  6:58   ` Aleksei Nikiforov
@ 2019-12-09  7:00   ` Aleksei Nikiforov
  1 sibling, 0 replies; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-09  7:00 UTC (permalink / raw)
  To: devel; +Cc: Aleksei Nikiforov

---
 apt/apt-pkg/contrib/mmap.cc | 15 +++++++++++++++
 apt/doc/apt.conf.5.sgml     |  4 ++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
index a3b06cc..cf01be9 100644
--- a/apt/apt-pkg/contrib/mmap.cc
+++ b/apt/apt-pkg/contrib/mmap.cc
@@ -265,6 +265,21 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
    // No pool is allocated, use an unallocated one
    if (I == Pools + PoolCount)
    {
+      static const bool debug_grow = _config->FindB("Debug::DynamicMMap::Allocate", false);
+
+      if (debug_grow)
+      {
+         Pool *pool_iter = Pools;
+         size_t pool_idx = 0;
+
+         _error->Warning(_("DynamicMMap::Allocate: allocating item of size %lu"), ItemSize);
+
+         for (; pool_idx < PoolCount; ++pool_iter, ++pool_idx)
+         {
+            _error->Warning(_("DynamicMMap::Allocate: Pool %zu, item size: %lu, start: %lu, count: %lu"), pool_idx, pool_iter->ItemSize, pool_iter->Start, pool_iter->Count);
+         }
+      }
+
       // Woops, we ran out, the calling code should allocate more.
       if (Empty == 0)
       {
diff --git a/apt/doc/apt.conf.5.sgml b/apt/doc/apt.conf.5.sgml
index 0a72e45..0026359 100644
--- a/apt/doc/apt.conf.5.sgml
+++ b/apt/doc/apt.conf.5.sgml
@@ -525,8 +525,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
    command line for each dpkg invokation. <literal/Debug::IdentCdrom/ will 
    disable the inclusion of statfs data in CDROM IDs.
    </para><para>
-   To debug issues related to dynamic memory allocation, an option
-   <literal/Debug::DynamicMMap::Grow/ may be used.
+   To debug issues related to dynamic memory allocation, options
+   <literal/Debug::DynamicMMap::Grow/ and <literal/Debug::DynamicMMap::Allocate/ may be used.
    </para>
  </RefSect1>
  
-- 
2.24.0



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-08 23:21       ` Dmitry V. Levin
@ 2019-12-09  7:08         ` Aleksei Nikiforov
  2019-12-10  0:07           ` Dmitry V. Levin
  0 siblings, 1 reply; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-09  7:08 UTC (permalink / raw)
  To: devel

09.12.2019 2:21, Dmitry V. Levin пишет:
> On Fri, Dec 06, 2019 at 06:36:55PM +0300, Aleksei Nikiforov wrote:
> [...]
>> @@ -85,11 +87,11 @@ class pkgCache::PkgIterator
>>      inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
>>      OkState State() const;
>>   
>> -   void ReMap(void const * const oldMap, void const * const newMap)
>> +   void ReMap(void *oldMap, void *newMap)
> 
> Is there any particular reason for stripping const here and in other
> similar places?
> 

Yes, it's needed due to issues emerging from mixing const and non-const 
pointers with new and allegedly more proper way of calculating rebased 
pointers.

> [...]
>> @@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
>>         Pool* oldPools = Pools;
>>         auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
>>         if (Pools != oldPools)
>> -         I += Pools - oldPools;
>> +         I = RebasePointer(I, oldPools, Pools);
>>   
>>         // Does the allocation failed ?
>>         if (!idxResult)
> 
> In my patch RebasePointer invocation was after the idxResult check,
> not before the check.
> 

Theoretically, order here might be important. In practice, it doesn't 
matter.

> By the way, in this and other similar cases,
> is there any reason for "Pools != oldPools" check?
> Is RebasePointer incapable of handling this, or is it an optimization?
> 

It's just an optimization, it may be removed.

> [...]
>> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
>> new file mode 100644
>> index 0000000..f6b3c15
>> --- /dev/null
>> +++ b/apt/apt-pkg/rebase_pointer.h
>> @@ -0,0 +1,16 @@
>> +#ifndef PKGLIB_REBASE_POINTER_H
>> +#define PKGLIB_REBASE_POINTER_H
>> +
>> +template <typename T>
>> +static inline T* RebasePointer(T *ptr, void *old_base, void *new_base)
>> +{
>> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(old_base)));
>> +}
>> +
>> +template <typename T>
>> +static inline const T* RebasePointer(const T *ptr, void *old_base, void *new_base)
>> +{
>> +   return reinterpret_cast<const T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<const char*>(ptr) - reinterpret_cast<char*>(old_base)));
>> +}
>> +
>> +#endif
> 
> Do we really need two templates here?
> 
> 

Yes, second template with const ptr is needed for 
rpmListParser::rpmListParser from rpmlistparser.cc.

Variable SeenPackages has type SeenPackagesType, which is a typedef to 
std::set<const char*,cstr_lt_pred>. Thus, elements are 'const char*', 
and either it should be const-casted to 'char*', which is ugly, or 
const-correctness should be achieved some other way, for example by 
getting rid of unimportant const qualifiers like in my changes.

And first template is needed for every other case with non-const ptr.

> 
> _______________________________________________
> Devel mailing list
> Devel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel
> 


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2] Fix pointer arithmetics
  2019-12-08 23:31   ` [devel] [PATCH for apt 2/2] " Dmitry V. Levin
@ 2019-12-09  7:09     ` Aleksei Nikiforov
  2019-12-09  7:16     ` [devel] [PATCH for apt 2/2 v3] " Aleksei Nikiforov
  1 sibling, 0 replies; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-09  7:09 UTC (permalink / raw)
  To: devel

09.12.2019 2:31, Dmitry V. Levin пишет:
> On Fri, Dec 06, 2019 at 04:16:06PM +0300, Aleksei Nikiforov wrote:
> [...]
>> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
>> new file mode 100644
>> index 0000000..efc4074
>> --- /dev/null
>> +++ b/apt/apt-pkg/rebase_pointer.h
>> @@ -0,0 +1,16 @@
>> +#ifndef PKGLIB_REBASE_POINTER_H
>> +#define PKGLIB_REBASE_POINTER_H
>> +
>> +template <typename T>
>> +static inline T* RebasePointer(T *ptr, const void * const old_base, const void * const new_base)
>> +{
>> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(ptr) + (reinterpret_cast<char const * const>(new_base) - reinterpret_cast<char const * const>(old_base)));
>> +}
>> +
>> +template <typename T>
>> +static inline const T* RebasePointer(const T *ptr, const void * const old_base, const void * const new_base)
>> +{
>> +   return reinterpret_cast<const T*>(reinterpret_cast<const char*>(ptr) + (reinterpret_cast<char const * const>(new_base) - reinterpret_cast<char const * const>(old_base)));
> 
> This line is way too long - about twice longer than a normal line of code.
> Please break long lines.
> 
> My edition of rebase_pointer.h had the maximum length of all lines within
> the traditional 80-symbol limit.
> 
> 

Sure, I'll update this code.

> 
> _______________________________________________
> Devel mailing list
> Devel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel
> 


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [devel] [PATCH for apt 2/2 v3] Fix pointer arithmetics
  2019-12-08 23:31   ` [devel] [PATCH for apt 2/2] " Dmitry V. Levin
  2019-12-09  7:09     ` Aleksei Nikiforov
@ 2019-12-09  7:16     ` Aleksei Nikiforov
  1 sibling, 0 replies; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-09  7:16 UTC (permalink / raw)
  To: devel; +Cc: Aleksei Nikiforov

This change should fix pointer arithmetic issues
which manifest on e2k architecture.
---
 apt/apt-pkg/Makefile.am           |  1 +
 apt/apt-pkg/cacheiterators.h      | 26 ++++++++++++++------------
 apt/apt-pkg/contrib/mmap.cc       |  8 +++++---
 apt/apt-pkg/pkgcachegen.cc        | 29 +++++++++++++++--------------
 apt/apt-pkg/pkgcachegen.h         |  6 +++---
 apt/apt-pkg/rebase_pointer.h      | 22 ++++++++++++++++++++++
 apt/apt-pkg/rpm/rpmlistparser.cc  |  5 +++--
 apt/apt-pkg/rpm/rpmpackagedata.cc |  2 +-
 8 files changed, 64 insertions(+), 35 deletions(-)
 create mode 100644 apt/apt-pkg/rebase_pointer.h

diff --git a/apt/apt-pkg/Makefile.am b/apt/apt-pkg/Makefile.am
index 4c0d234..d038d01 100644
--- a/apt/apt-pkg/Makefile.am
+++ b/apt/apt-pkg/Makefile.am
@@ -94,6 +94,7 @@ libapt_pkg_la_SOURCES = \
 	pkgsystem.h \
 	policy.cc \
 	policy.h \
+	rebase_pointer.h \
 	repository.cc \
 	repository.h \
 	scopeexit.h \
diff --git a/apt/apt-pkg/cacheiterators.h b/apt/apt-pkg/cacheiterators.h
index a4bf670..118838e 100644
--- a/apt/apt-pkg/cacheiterators.h
+++ b/apt/apt-pkg/cacheiterators.h
@@ -34,6 +34,8 @@
 #pragma interface "apt-pkg/cacheiterators.h"
 #endif 
 
+#include <apt-pkg/rebase_pointer.h>
+
 #include <set>
 
 // Package Iterator
@@ -85,11 +87,11 @@ class pkgCache::PkgIterator
    inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
    OkState State() const;
 
-   void ReMap(void const * const oldMap, void const * const newMap)
+   void ReMap(void *oldMap, void *newMap)
    {
       if (Owner == 0 || Pkg == 0)
          return;
-      Pkg += static_cast<Package const *>(newMap) - static_cast<Package const *>(oldMap);
+      Pkg = RebasePointer(Pkg, oldMap, newMap);
    }
 
    // Constructors
@@ -147,11 +149,11 @@ class pkgCache::VerIterator
    bool Automatic() const;
    VerFileIterator NewestFile() const;
 
-   void ReMap(void const * const oldMap, void const * const newMap)
+   void ReMap(void *oldMap, void *newMap)
    {
       if (Owner == 0 || Ver == 0)
          return;
-      Ver += static_cast<Version const *>(newMap) - static_cast<Version const *>(oldMap);
+      Ver = RebasePointer(Ver, oldMap, newMap);
    }
 
    inline VerIterator() : Ver(0), Owner(0) {};   
@@ -220,11 +222,11 @@ class pkgCache::DepIterator
    inline const char *CompType() {return Owner->CompType(Dep->CompareOp);};
    inline const char *DepType() {return Owner->DepType(Dep->Type);};
 
-   void ReMap(void const * const oldMap, void const * const newMap)
+   void ReMap(void *oldMap, void *newMap)
    {
       if (Owner == 0 || Dep == 0)
          return;
-      Dep += static_cast<Dependency const *>(newMap) - static_cast<Dependency const *>(oldMap);
+      Dep = RebasePointer(Dep, oldMap, newMap);
    }
 
    inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) :
@@ -279,11 +281,11 @@ class pkgCache::PrvIterator
    inline PkgIterator OwnerPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[Prv->Version].ParentPkg);};
    inline unsigned long long Index() const {return Prv - Owner->ProvideP;};
 
-   void ReMap(void const * const oldMap, void const * const newMap)
+   void ReMap(void *oldMap, void *newMap)
    {
       if (Owner == 0 || Prv == 0)
          return;
-      Prv += static_cast<Provides const *>(newMap) - static_cast<Provides const *>(oldMap);
+      Prv = RebasePointer(Prv, oldMap, newMap);
    }
 
    inline PrvIterator() : Prv(0), Type(PrvVer), Owner(0)  {};
@@ -342,11 +344,11 @@ class pkgCache::PkgFileIterator
    bool IsOk();
    string RelStr();
 
-   void ReMap(void const * const oldMap, void const * const newMap)
+   void ReMap(void *oldMap, void *newMap)
    {
       if (Owner == 0 || File == 0)
          return;
-      File += static_cast<PackageFile const *>(newMap) - static_cast<PackageFile const *>(oldMap);
+      File = RebasePointer(File, oldMap, newMap);
    }
 
    // Constructors
@@ -383,11 +385,11 @@ class pkgCache::VerFileIterator
    inline PkgFileIterator File() const {return PkgFileIterator(*Owner,FileP->File + Owner->PkgFileP);};
    inline unsigned long long Index() const {return FileP - Owner->VerFileP;};
 
-   void ReMap(void const * const oldMap, void const * const newMap)
+   void ReMap(void *oldMap, void *newMap)
    {
       if (Owner == 0 || FileP == 0)
          return;
-      FileP += static_cast<VerFile const *>(newMap) - static_cast<VerFile const *>(oldMap);
+      FileP = RebasePointer(FileP, oldMap, newMap);
    }
 
    inline VerFileIterator() : Owner(0), FileP(0) {};
diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
index cf01be9..35f1a25 100644
--- a/apt/apt-pkg/contrib/mmap.cc
+++ b/apt/apt-pkg/contrib/mmap.cc
@@ -30,6 +30,7 @@
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/mmap.h>
 #include <apt-pkg/error.h>
+#include <apt-pkg/rebase_pointer.h>
 
 #include <apti18n.h>
 
@@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
       Pool* oldPools = Pools;
       auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
       if (Pools != oldPools)
-         I += Pools - oldPools;
+         I = RebasePointer(I, oldPools, Pools);
 
       // Does the allocation failed ?
       if (!idxResult)
@@ -371,7 +372,7 @@ bool DynamicMMap::Grow(unsigned long long size)
       Fd->Write(&C,sizeof(C));
    }
 
-   unsigned long const poolOffset = Pools - ((Pool*) Base);
+   void *old_base = Base;
 
    if (Fd != 0)
    {
@@ -408,7 +409,8 @@ bool DynamicMMap::Grow(unsigned long long size)
       memset((char*)Base + WorkSpace, 0, newSize - WorkSpace);
    }
 
-   Pools = (Pool*) Base + poolOffset;
+   if (Base != old_base)
+      Pools = RebasePointer(Pools, old_base, Base);
    WorkSpace = newSize;
 
    return true;
diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc
index 654c81c..37364e9 100644
--- a/apt/apt-pkg/pkgcachegen.cc
+++ b/apt/apt-pkg/pkgcachegen.cc
@@ -26,6 +26,7 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/rebase_pointer.h>
 
 #include <apti18n.h>
 
@@ -109,18 +110,18 @@ pkgCacheGenerator::~pkgCacheGenerator()
    Map.Sync(0,sizeof(pkgCache::Header));
 }
 									/*}}}*/
-void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newMap)
+void pkgCacheGenerator::ReMap(void *oldMap, void *newMap)
 {
    if (oldMap == newMap)
       return;
 
    Cache.ReMap(false);
 
-   CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap;
+   CurrentFile = RebasePointer(CurrentFile, oldMap, newMap);
 
    for (size_t i = 0; i < _count(UniqHash); ++i)
       if (UniqHash[i] != 0)
-         UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap;
+         UniqHash[i] = RebasePointer(UniqHash[i], oldMap, newMap);
 
    for (auto i = Dynamic<pkgCache::PkgIterator>::toReMap.begin();
         i != Dynamic<pkgCache::PkgIterator>::toReMap.end(); ++i)
@@ -147,7 +148,7 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
 // CacheGenerator::WriteStringInMap					/*{{{*/
 std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(const char *String,
 					unsigned long Len) {
-   void const * const oldMap = Map.Data();
+   void *oldMap = Map.Data();
    const auto index = Map.WriteString(String, Len);
    if (index)
       ReMap(oldMap, Map.Data());
@@ -156,7 +157,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(cons
 									/*}}}*/
 // CacheGenerator::WriteStringInMap					/*{{{*/
 std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(const char *String) {
-   void const * const oldMap = Map.Data();
+   void *oldMap = Map.Data();
    const auto index = Map.WriteString(String);
    if (index)
       ReMap(oldMap, Map.Data());
@@ -164,7 +165,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(cons
 }
 									/*}}}*/
 std::experimental::optional<map_ptrloc> pkgCacheGenerator::AllocateInMap(unsigned long size) {/*{{{*/
-   void const * const oldMap = Map.Data();
+   void *oldMap = Map.Data();
    const auto index = Map.Allocate(size);
    if (index)
       ReMap(oldMap, Map.Data());
@@ -229,7 +230,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
       pkgCache::VerIterator Ver = Pkg.VersionList();
       Dynamic<pkgCache::VerIterator> DynVer(Ver);
       map_ptrloc *Last = &Pkg->VersionList;
-      const void * oldMap = Map.Data();
+      void *oldMap = Map.Data();
       int Res = 1;
       for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
       {
@@ -271,7 +272,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
 
       if (oldMap != Map.Data())
       {
-         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+         Last = RebasePointer(Last, oldMap, Map.Data());
          oldMap = Map.Data();
       }
 
@@ -297,7 +298,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
                               PackageName.c_str(), 1);
 
       if (oldMap != Map.Data())
-         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+         Last = RebasePointer(Last, oldMap, Map.Data());
       *Last = *verindex;
 
       Ver->ParentPkg = Pkg.Index();
@@ -553,7 +554,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
 					       unsigned int Op,
 					       unsigned int Type)
 {
-   void const * const oldMap = Owner->Map.Data();
+   void *oldMap = Owner->Map.Data();
    pkgCache &Cache = Owner->Cache;
    
    // Get a structure
@@ -605,7 +606,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
 	 OldDepLast = &D->NextDepends;
       OldDepVer = Ver;
    } else if (oldMap != Owner->Map.Data())
-      OldDepLast += (map_ptrloc*) Owner->Map.Data() - (map_ptrloc*) oldMap;
+      OldDepLast = RebasePointer(OldDepLast, oldMap, Owner->Map.Data());
 
    // Is it a file dependency?
    if (PackageName[0] == '/')
@@ -739,7 +740,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
    }
    
    // Get a structure
-   void const * const oldMap = Map.Data();
+   void *oldMap = Map.Data();
    const auto Item = AllocateInMap(sizeof(pkgCache::StringItem));
    const auto idxString = WriteStringInMap(S, Size);
    if ((!Item) || (!idxString))
@@ -747,8 +748,8 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
 
    if (oldMap != Map.Data())
    {
-      Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
-      I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap;
+      Last = RebasePointer(Last, oldMap, Map.Data());
+      I = RebasePointer(I, oldMap, Map.Data());
    }
 
    *Last = *Item;
diff --git a/apt/apt-pkg/pkgcachegen.h b/apt/apt-pkg/pkgcachegen.h
index 77075a6..0faf6e1 100644
--- a/apt/apt-pkg/pkgcachegen.h
+++ b/apt/apt-pkg/pkgcachegen.h
@@ -72,7 +72,7 @@ class pkgCacheGenerator
    class DynamicFunction
    {
    public:
-      typedef std::function<void(const void *, const void *)> function;
+      typedef std::function<void(void *, void *)> function;
 
       static std::set<DynamicFunction*> toReMap;
 
@@ -93,7 +93,7 @@ class pkgCacheGenerator
          toReMap.erase(this);
       }
 
-      void call(const void *oldMap, const void *newMap)
+      void call(void *oldMap, void *newMap)
       {
          if (m_function)
             m_function(oldMap, newMap);
@@ -140,7 +140,7 @@ class pkgCacheGenerator
    // CNC:2003-03-18
    inline void ResetFileDeps() {FoundFileDeps = false;};
 
-   void ReMap(void const * const oldMap, void const * const newMap);
+   void ReMap(void *oldMap, void *newMap);
 
    pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress);
    ~pkgCacheGenerator();
diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
new file mode 100644
index 0000000..3b66b98
--- /dev/null
+++ b/apt/apt-pkg/rebase_pointer.h
@@ -0,0 +1,22 @@
+#ifndef PKGLIB_REBASE_POINTER_H
+#define PKGLIB_REBASE_POINTER_H
+
+template <typename T>
+static inline T* RebasePointer(T *ptr,
+                               void *old_base, void *new_base)
+{
+   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base)
+      + (reinterpret_cast<char*>(ptr)
+         - reinterpret_cast<char*>(old_base)));
+}
+
+template <typename T>
+static inline const T* RebasePointer(const T *ptr,
+                                     void *old_base, void *new_base)
+{
+   return reinterpret_cast<const T*>(reinterpret_cast<char*>(new_base)
+      + (reinterpret_cast<const char*>(ptr)
+         - reinterpret_cast<char*>(old_base)));
+}
+
+#endif
diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc b/apt/apt-pkg/rpm/rpmlistparser.cc
index 9b2e9ad..bd13b99 100644
--- a/apt/apt-pkg/rpm/rpmlistparser.cc
+++ b/apt/apt-pkg/rpm/rpmlistparser.cc
@@ -25,6 +25,7 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/crc-16.h>
 #include <apt-pkg/tagfile.h>
+#include <apt-pkg/rebase_pointer.h>
 
 #include <apti18n.h>
 
@@ -50,13 +51,13 @@ rpmListParser::rpmListParser(RPMHandler *Handler)
    {
       SeenPackages.reset(new SeenPackagesType);
       m_SeenPackagesRealloc.reset(new pkgCacheGenerator::DynamicFunction(
-         [this] (void const *oldMap, void const *newMap)
+         [this] (void *oldMap, void *newMap)
       {
          SeenPackagesType tmp;
 
          for (auto iter: *SeenPackages)
          {
-            tmp.insert(iter + (static_cast<const char *>(newMap) - static_cast<const char *>(oldMap)));
+            tmp.insert(RebasePointer(iter, oldMap, newMap));
          }
 
          SeenPackages->swap(tmp);
diff --git a/apt/apt-pkg/rpm/rpmpackagedata.cc b/apt/apt-pkg/rpm/rpmpackagedata.cc
index 61c15d5..d6c677b 100644
--- a/apt/apt-pkg/rpm/rpmpackagedata.cc
+++ b/apt/apt-pkg/rpm/rpmpackagedata.cc
@@ -23,7 +23,7 @@ RPMPackageData::RPMPackageData()
 #endif
 {
    m_VerMapRealloc.reset(new pkgCacheGenerator::DynamicFunction(
-      [this] (void const *oldMap, void const *newMap)
+      [this] (void *oldMap, void *newMap)
    {
       for (auto iter1 = VerMap.begin(); iter1 != VerMap.end(); ++iter1)
       {
-- 
2.24.0



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 1/2] Add option for debugging DynamicMMap::Allocate
  2019-12-09  6:58   ` Aleksei Nikiforov
@ 2019-12-09 10:24     ` Dmitry V. Levin
  2019-12-09 11:03       ` [devel] [PATCH for apt 1/2 v3] Add Debug::DynamicMMap::Allocate option Aleksei Nikiforov
  0 siblings, 1 reply; 34+ messages in thread
From: Dmitry V. Levin @ 2019-12-09 10:24 UTC (permalink / raw)
  To: Aleksei Nikiforov; +Cc: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 950 bytes --]

On Mon, Dec 09, 2019 at 09:58:55AM +0300, Aleksei Nikiforov wrote:
> 09.12.2019 1:50, Dmitry V. Levin пишет:
> > On Fri, Dec 06, 2019 at 04:16:05PM +0300, Aleksei Nikiforov wrote:
> >> ---
> >>   apt/apt-pkg/contrib/mmap.cc | 15 +++++++++++++++
> >>   apt/doc/apt.conf.5.sgml     |  2 +-
> >>   2 files changed, 16 insertions(+), 1 deletion(-)
> > 
> > I suggest adding the name of the new option to the commit message
> > so it would be git-grep'able, for example:
> > 
> > Add Debug::DynamicMMap::Allocate option
> > 
> > Add a new option for debugging DynamicMMap::Allocate.
> 
> But option name is already in commit message. See the email subject 
> which is also a part of commit message. Why is it needed to duplicate it?

I don't see a duplication here, but anyway, this is just an example, and
"Add Debug::DynamicMMap::Allocate option" would be better than
"Add option for debugging DynamicMMap::Allocate".


-- 
ldv

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [devel] [PATCH for apt 1/2 v3] Add Debug::DynamicMMap::Allocate option
  2019-12-09 10:24     ` Dmitry V. Levin
@ 2019-12-09 11:03       ` Aleksei Nikiforov
  2019-12-09 22:59         ` Dmitry V. Levin
  0 siblings, 1 reply; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-09 11:03 UTC (permalink / raw)
  To: devel; +Cc: Aleksei Nikiforov

---
 apt/apt-pkg/contrib/mmap.cc | 15 +++++++++++++++
 apt/doc/apt.conf.5.sgml     |  4 ++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
index a3b06cc..cf01be9 100644
--- a/apt/apt-pkg/contrib/mmap.cc
+++ b/apt/apt-pkg/contrib/mmap.cc
@@ -265,6 +265,21 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
    // No pool is allocated, use an unallocated one
    if (I == Pools + PoolCount)
    {
+      static const bool debug_grow = _config->FindB("Debug::DynamicMMap::Allocate", false);
+
+      if (debug_grow)
+      {
+         Pool *pool_iter = Pools;
+         size_t pool_idx = 0;
+
+         _error->Warning(_("DynamicMMap::Allocate: allocating item of size %lu"), ItemSize);
+
+         for (; pool_idx < PoolCount; ++pool_iter, ++pool_idx)
+         {
+            _error->Warning(_("DynamicMMap::Allocate: Pool %zu, item size: %lu, start: %lu, count: %lu"), pool_idx, pool_iter->ItemSize, pool_iter->Start, pool_iter->Count);
+         }
+      }
+
       // Woops, we ran out, the calling code should allocate more.
       if (Empty == 0)
       {
diff --git a/apt/doc/apt.conf.5.sgml b/apt/doc/apt.conf.5.sgml
index 0a72e45..0026359 100644
--- a/apt/doc/apt.conf.5.sgml
+++ b/apt/doc/apt.conf.5.sgml
@@ -525,8 +525,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
    command line for each dpkg invokation. <literal/Debug::IdentCdrom/ will 
    disable the inclusion of statfs data in CDROM IDs.
    </para><para>
-   To debug issues related to dynamic memory allocation, an option
-   <literal/Debug::DynamicMMap::Grow/ may be used.
+   To debug issues related to dynamic memory allocation, options
+   <literal/Debug::DynamicMMap::Grow/ and <literal/Debug::DynamicMMap::Allocate/ may be used.
    </para>
  </RefSect1>
  
-- 
2.24.0



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 1/2 v3] Add Debug::DynamicMMap::Allocate option
  2019-12-09 11:03       ` [devel] [PATCH for apt 1/2 v3] Add Debug::DynamicMMap::Allocate option Aleksei Nikiforov
@ 2019-12-09 22:59         ` Dmitry V. Levin
  0 siblings, 0 replies; 34+ messages in thread
From: Dmitry V. Levin @ 2019-12-09 22:59 UTC (permalink / raw)
  To: Aleksei Nikiforov; +Cc: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 4439 bytes --]

On Mon, Dec 09, 2019 at 02:03:00PM +0300, Aleksei Nikiforov wrote:
> ---
>  apt/apt-pkg/contrib/mmap.cc | 15 +++++++++++++++
>  apt/doc/apt.conf.5.sgml     |  4 ++--
>  2 files changed, 17 insertions(+), 2 deletions(-)
> 
> diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
> index a3b06cc..cf01be9 100644
> --- a/apt/apt-pkg/contrib/mmap.cc
> +++ b/apt/apt-pkg/contrib/mmap.cc
> @@ -265,6 +265,21 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
>     // No pool is allocated, use an unallocated one
>     if (I == Pools + PoolCount)
>     {
> +      static const bool debug_grow = _config->FindB("Debug::DynamicMMap::Allocate", false);
> +
> +      if (debug_grow)
> +      {
> +         Pool *pool_iter = Pools;
> +         size_t pool_idx = 0;
> +
> +         _error->Warning(_("DynamicMMap::Allocate: allocating item of size %lu"), ItemSize);
> +
> +         for (; pool_idx < PoolCount; ++pool_iter, ++pool_idx)
> +         {
> +            _error->Warning(_("DynamicMMap::Allocate: Pool %zu, item size: %lu, start: %lu, count: %lu"), pool_idx, pool_iter->ItemSize, pool_iter->Start, pool_iter->Count);
> +         }
> +      }
> +
>        // Woops, we ran out, the calling code should allocate more.
>        if (Empty == 0)
>        {
> diff --git a/apt/doc/apt.conf.5.sgml b/apt/doc/apt.conf.5.sgml
> index 0a72e45..0026359 100644
> --- a/apt/doc/apt.conf.5.sgml
> +++ b/apt/doc/apt.conf.5.sgml
> @@ -525,8 +525,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
>     command line for each dpkg invokation. <literal/Debug::IdentCdrom/ will 
>     disable the inclusion of statfs data in CDROM IDs.
>     </para><para>
> -   To debug issues related to dynamic memory allocation, an option
> -   <literal/Debug::DynamicMMap::Grow/ may be used.
> +   To debug issues related to dynamic memory allocation, options
> +   <literal/Debug::DynamicMMap::Grow/ and <literal/Debug::DynamicMMap::Allocate/ may be used.
>     </para>
>   </RefSect1>
>   

Sadly, for some reason most of my comments were ignored.

I'm going to apply the following edition of this patch:

From a60c3cb4fd06c84c61358af597a88717ecc36c05 Mon Sep 17 00:00:00 2001
From: Aleksei Nikiforov <darktemplar@altlinux.org>
Date: Mon, 9 Dec 2019 14:03:00 +0300
Subject: [PATCH] Add Debug::DynamicMMap::Allocate option

Co-developed-by: Dmitry V. Levin <ldv@altlinux.org>
---
 apt/apt-pkg/contrib/mmap.cc | 17 +++++++++++++++++
 apt/doc/apt.conf.5.sgml     |  4 ++--
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
index 779d7a6..56c3cce 100644
--- a/apt/apt-pkg/contrib/mmap.cc
+++ b/apt/apt-pkg/contrib/mmap.cc
@@ -266,6 +266,23 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
    // No pool is allocated, use an unallocated one
    if (I == Pools + PoolCount)
    {
+      static const bool debug_allocate =
+	      _config->FindB("Debug::DynamicMMap::Allocate", false);
+
+      if (debug_allocate)
+      {
+         _error->Warning(_("DynamicMMap::Allocate: allocating item of size %lu"),
+                         ItemSize);
+
+         for (unsigned int i = 0; i < PoolCount; ++i)
+         {
+            _error->Warning(_("DynamicMMap::Allocate: Pool %u, item size: %lu"
+                              ", start: %lu, count: %lu"),
+                            i, Pools[i].ItemSize,
+                            Pools[i].Start, Pools[i].Count);
+         }
+      }
+
       // Woops, we ran out, the calling code should allocate more.
       if (Empty == 0)
       {
diff --git a/apt/doc/apt.conf.5.sgml b/apt/doc/apt.conf.5.sgml
index 0a72e45..0026359 100644
--- a/apt/doc/apt.conf.5.sgml
+++ b/apt/doc/apt.conf.5.sgml
@@ -525,8 +525,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
    command line for each dpkg invokation. <literal/Debug::IdentCdrom/ will 
    disable the inclusion of statfs data in CDROM IDs.
    </para><para>
-   To debug issues related to dynamic memory allocation, an option
-   <literal/Debug::DynamicMMap::Grow/ may be used.
+   To debug issues related to dynamic memory allocation, options
+   <literal/Debug::DynamicMMap::Grow/ and <literal/Debug::DynamicMMap::Allocate/ may be used.
    </para>
  </RefSect1>
  
-- 
ldv

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [devel] [PATCH apt 0/3] Fix 0.5.15lorg2-alt70~9 fallout
  2019-12-06 13:16 ` [devel] [PATCH for apt 2/2] Fix pointer arithmetics Aleksei Nikiforov
  2019-12-06 13:36   ` Ivan A. Melnikov
  2019-12-08 23:31   ` [devel] [PATCH for apt 2/2] " Dmitry V. Levin
@ 2019-12-09 23:54   ` Dmitry V. Levin
  2019-12-09 23:56     ` [devel] [PATCH apt 1/3] apt-pkg/cacheiterators.h: revert #include <set> Dmitry V. Levin
                       ` (2 more replies)
  2 siblings, 3 replies; 34+ messages in thread
From: Dmitry V. Levin @ 2019-12-09 23:54 UTC (permalink / raw)
  To: ALT Devel discussion list

Commit 6d5e6a689d07de8feef2cbecb24bc42d5994861b aka 0.5.15lorg2-alt70~9
("apt-pkg/pkgcachegen.{cc,h} changes") among many useful changes
introduced a few problematic ones, too.

This series hopefully cleans up the fallout.

Dmitry V. Levin (3):
  apt-pkg/cacheiterators.h: revert #include <set>
  apt-pkg/contrib/mmap.cc: revert confusing change of Flags to this->Flags
  Fix UB in pointer arithmetic

 apt/apt-pkg/Makefile.am          |  1 +
 apt/apt-pkg/cacheiterators.h     | 14 +++++++-------
 apt/apt-pkg/contrib/mmap.cc      | 28 ++++++++++++++--------------
 apt/apt-pkg/pkgcachegen.cc       | 27 +++++++++++----------------
 apt/apt-pkg/rebase_pointer.h     | 25 +++++++++++++++++++++++++
 apt/apt-pkg/rpm/rpmlistparser.cc |  3 ++-
 6 files changed, 60 insertions(+), 38 deletions(-)
 create mode 100644 apt/apt-pkg/rebase_pointer.h

-- 
ldv


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [devel] [PATCH apt 1/3] apt-pkg/cacheiterators.h: revert #include <set>
  2019-12-09 23:54   ` [devel] [PATCH apt 0/3] Fix 0.5.15lorg2-alt70~9 fallout Dmitry V. Levin
@ 2019-12-09 23:56     ` Dmitry V. Levin
  2019-12-09 23:56     ` [devel] [PATCH apt 2/3] apt-pkg/contrib/mmap.cc: revert confusing change of Flags to this->Flags Dmitry V. Levin
  2019-12-09 23:56     ` [devel] [PATCH apt 3/3] Fix UB in pointer arithmetic Dmitry V. Levin
  2 siblings, 0 replies; 34+ messages in thread
From: Dmitry V. Levin @ 2019-12-09 23:56 UTC (permalink / raw)
  To: ALT Devel discussion list

Commit 6d5e6a689d07de8feef2cbecb24bc42d5994861b aka 0.5.15lorg2-alt70~9
among other changes added #include <set> without any reason whatsoever.

Fixes: 6d5e6a68 ("apt-pkg/pkgcachegen.{cc,h} changes")
---
 apt/apt-pkg/cacheiterators.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/apt/apt-pkg/cacheiterators.h b/apt/apt-pkg/cacheiterators.h
index bad1e11..9dffeb3 100644
--- a/apt/apt-pkg/cacheiterators.h
+++ b/apt/apt-pkg/cacheiterators.h
@@ -34,8 +34,6 @@
 #pragma interface "apt-pkg/cacheiterators.h"
 #endif 
 
-#include <set>
-
 // Package Iterator
 class pkgCache::PkgIterator
 {
-- 
ldv


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [devel] [PATCH apt 2/3] apt-pkg/contrib/mmap.cc: revert confusing change of Flags to this->Flags
  2019-12-09 23:54   ` [devel] [PATCH apt 0/3] Fix 0.5.15lorg2-alt70~9 fallout Dmitry V. Levin
  2019-12-09 23:56     ` [devel] [PATCH apt 1/3] apt-pkg/cacheiterators.h: revert #include <set> Dmitry V. Levin
@ 2019-12-09 23:56     ` Dmitry V. Levin
  2019-12-09 23:56     ` [devel] [PATCH apt 3/3] Fix UB in pointer arithmetic Dmitry V. Levin
  2 siblings, 0 replies; 34+ messages in thread
From: Dmitry V. Levin @ 2019-12-09 23:56 UTC (permalink / raw)
  To: ALT Devel discussion list

Commit 6d5e6a689d07de8feef2cbecb24bc42d5994861b aka 0.5.15lorg2-alt70~9
among other changes replaced Flags with this->Flags in many places where
this is not just unnecessary but also confusing.  Only those places
where this->Flags is modified had to be changed this way.

Fixes: 6d5e6a68 ("apt-pkg/pkgcachegen.{cc,h} changes")
---
 apt/apt-pkg/contrib/mmap.cc | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
index a3b06cc..2064fc4 100644
--- a/apt/apt-pkg/contrib/mmap.cc
+++ b/apt/apt-pkg/contrib/mmap.cc
@@ -46,7 +46,7 @@
 MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0),
                      Base(nullptr)
 {
-   if ((this->Flags & NoImmMap) != NoImmMap)
+   if ((Flags & NoImmMap) != NoImmMap)
       Map(F);
 }
 									/*}}}*/
@@ -76,9 +76,9 @@ bool MMap::Map(FileFd &Fd)
    // Set the permissions.
    int Prot = PROT_READ;
    int Map = MAP_SHARED;
-   if ((this->Flags & ReadOnly) != ReadOnly)
+   if ((Flags & ReadOnly) != ReadOnly)
       Prot |= PROT_WRITE;
-   if ((this->Flags & Public) != Public)
+   if ((Flags & Public) != Public)
       Map = MAP_PRIVATE;
    
    if (iSize == 0)
@@ -97,7 +97,7 @@ bool MMap::Map(FileFd &Fd)
 /* */
 bool MMap::Close(bool DoSync)
 {
-   if ((this->Flags & UnMapped) == UnMapped || validData() == false || iSize == 0)
+   if ((Flags & UnMapped) == UnMapped || validData() == false || iSize == 0)
       return true;
    
    if (DoSync == true)
@@ -117,11 +117,11 @@ bool MMap::Close(bool DoSync)
    not return till all IO is complete */
 bool MMap::Sync()
 {   
-   if ((this->Flags & UnMapped) == UnMapped)
+   if ((Flags & UnMapped) == UnMapped)
       return true;
    
 #ifdef _POSIX_SYNCHRONIZED_IO   
-   if ((this->Flags & ReadOnly) != ReadOnly)
+   if ((Flags & ReadOnly) != ReadOnly)
       if (msync((char *)Base,iSize,MS_SYNC) != 0)
 	 return _error->Errno("msync","Unable to write mmap");
 #endif   
@@ -133,12 +133,12 @@ bool MMap::Sync()
 /* */
 bool MMap::Sync(unsigned long Start,unsigned long Stop)
 {
-   if ((this->Flags & UnMapped) == UnMapped)
+   if ((Flags & UnMapped) == UnMapped)
       return true;
    
 #ifdef _POSIX_SYNCHRONIZED_IO
    unsigned long PSize = sysconf(_SC_PAGESIZE);
-   if ((this->Flags & ReadOnly) != ReadOnly)
+   if ((Flags & ReadOnly) != ReadOnly)
       if (msync((char *)Base+(int)(Start/PSize)*PSize,Stop - Start,MS_SYNC) != 0)
 	 return _error->Errno("msync","Unable to write mmap");
 #endif   
@@ -362,7 +362,7 @@ bool DynamicMMap::Grow(unsigned long long size)
    {
       void *tmp_base = MAP_FAILED;
 #ifdef MREMAP_MAYMOVE
-      if ((this->Flags & Moveable) == Moveable)
+      if ((Flags & Moveable) == Moveable)
          tmp_base = mremap(Base, WorkSpace, newSize, MREMAP_MAYMOVE);
       else
 #endif
@@ -376,7 +376,7 @@ bool DynamicMMap::Grow(unsigned long long size)
 
       Base = tmp_base;
    } else {
-      if ((this->Flags & Moveable) != Moveable)
+      if ((Flags & Moveable) != Moveable)
          return false;
 
       void *tmp_base = realloc(Base, newSize);
-- 
ldv


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [devel] [PATCH apt 3/3] Fix UB in pointer arithmetic
  2019-12-09 23:54   ` [devel] [PATCH apt 0/3] Fix 0.5.15lorg2-alt70~9 fallout Dmitry V. Levin
  2019-12-09 23:56     ` [devel] [PATCH apt 1/3] apt-pkg/cacheiterators.h: revert #include <set> Dmitry V. Levin
  2019-12-09 23:56     ` [devel] [PATCH apt 2/3] apt-pkg/contrib/mmap.cc: revert confusing change of Flags to this->Flags Dmitry V. Levin
@ 2019-12-09 23:56     ` Dmitry V. Levin
  2019-12-10  8:18       ` Aleksei Nikiforov
  2 siblings, 1 reply; 34+ messages in thread
From: Dmitry V. Levin @ 2019-12-09 23:56 UTC (permalink / raw)
  To: ALT Devel discussion list

Commit 6d5e6a689d07de8feef2cbecb24bc42d5994861b aka 0.5.15lorg2-alt70~9
among other changes introduced UB in pointer arithmetic by casting raw
pointers to specific types.

Fix this by introducing two helpers for rebasing pointers in a safe way.

Co-developed-by: Aleksei Nikiforov <darktemplar@altlinux.org>
Fixes: 6d5e6a68 ("apt-pkg/pkgcachegen.{cc,h} changes")
---
 apt/apt-pkg/Makefile.am          |  1 +
 apt/apt-pkg/cacheiterators.h     | 14 ++++++++------
 apt/apt-pkg/contrib/mmap.cc      |  8 ++++----
 apt/apt-pkg/pkgcachegen.cc       | 27 +++++++++++----------------
 apt/apt-pkg/rebase_pointer.h     | 25 +++++++++++++++++++++++++
 apt/apt-pkg/rpm/rpmlistparser.cc |  3 ++-
 6 files changed, 51 insertions(+), 27 deletions(-)
 create mode 100644 apt/apt-pkg/rebase_pointer.h

diff --git a/apt/apt-pkg/Makefile.am b/apt/apt-pkg/Makefile.am
index 4c0d234..d038d01 100644
--- a/apt/apt-pkg/Makefile.am
+++ b/apt/apt-pkg/Makefile.am
@@ -94,6 +94,7 @@ libapt_pkg_la_SOURCES = \
 	pkgsystem.h \
 	policy.cc \
 	policy.h \
+	rebase_pointer.h \
 	repository.cc \
 	repository.h \
 	scopeexit.h \
diff --git a/apt/apt-pkg/cacheiterators.h b/apt/apt-pkg/cacheiterators.h
index 9dffeb3..3c60cb8 100644
--- a/apt/apt-pkg/cacheiterators.h
+++ b/apt/apt-pkg/cacheiterators.h
@@ -34,6 +34,8 @@
 #pragma interface "apt-pkg/cacheiterators.h"
 #endif 
 
+#include <apt-pkg/rebase_pointer.h>
+
 // Package Iterator
 class pkgCache::PkgIterator
 {
@@ -87,7 +89,7 @@ class pkgCache::PkgIterator
    {
       if (Owner == 0 || Pkg == 0)
          return;
-      Pkg += static_cast<Package const *>(newMap) - static_cast<Package const *>(oldMap);
+      RebasePointer(Pkg, oldMap, newMap);
    }
 
    // Constructors
@@ -149,7 +151,7 @@ class pkgCache::VerIterator
    {
       if (Owner == 0 || Ver == 0)
          return;
-      Ver += static_cast<Version const *>(newMap) - static_cast<Version const *>(oldMap);
+      RebasePointer(Ver, oldMap, newMap);
    }
 
    inline VerIterator() : Ver(0), Owner(0) {};   
@@ -222,7 +224,7 @@ class pkgCache::DepIterator
    {
       if (Owner == 0 || Dep == 0)
          return;
-      Dep += static_cast<Dependency const *>(newMap) - static_cast<Dependency const *>(oldMap);
+      RebasePointer(Dep, oldMap, newMap);
    }
 
    inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) :
@@ -281,7 +283,7 @@ class pkgCache::PrvIterator
    {
       if (Owner == 0 || Prv == 0)
          return;
-      Prv += static_cast<Provides const *>(newMap) - static_cast<Provides const *>(oldMap);
+      RebasePointer(Prv, oldMap, newMap);
    }
 
    inline PrvIterator() : Prv(0), Type(PrvVer), Owner(0)  {};
@@ -344,7 +346,7 @@ class pkgCache::PkgFileIterator
    {
       if (Owner == 0 || File == 0)
          return;
-      File += static_cast<PackageFile const *>(newMap) - static_cast<PackageFile const *>(oldMap);
+      RebasePointer(File, oldMap, newMap);
    }
 
    // Constructors
@@ -385,7 +387,7 @@ class pkgCache::VerFileIterator
    {
       if (Owner == 0 || FileP == 0)
          return;
-      FileP += static_cast<VerFile const *>(newMap) - static_cast<VerFile const *>(oldMap);
+      RebasePointer(FileP, oldMap, newMap);
    }
 
    inline VerFileIterator() : Owner(0), FileP(0) {};
diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
index 2064fc4..779d7a6 100644
--- a/apt/apt-pkg/contrib/mmap.cc
+++ b/apt/apt-pkg/contrib/mmap.cc
@@ -30,6 +30,7 @@
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/mmap.h>
 #include <apt-pkg/error.h>
+#include <apt-pkg/rebase_pointer.h>
 
 #include <apti18n.h>
 
@@ -285,13 +286,12 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
       I->Count = size/ItemSize;
       Pool* oldPools = Pools;
       auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
-      if (Pools != oldPools)
-         I += Pools - oldPools;
 
       // Does the allocation failed ?
       if (!idxResult)
          return idxResult;
 
+      RebasePointer(I, oldPools, Pools);
       Result = *idxResult;
       I->Start = Result;
    }
@@ -356,7 +356,7 @@ bool DynamicMMap::Grow(unsigned long long size)
       Fd->Write(&C,sizeof(C));
    }
 
-   unsigned long const poolOffset = Pools - ((Pool*) Base);
+   const void *old_base = Base;
 
    if (Fd != 0)
    {
@@ -393,7 +393,7 @@ bool DynamicMMap::Grow(unsigned long long size)
       memset((char*)Base + WorkSpace, 0, newSize - WorkSpace);
    }
 
-   Pools = (Pool*) Base + poolOffset;
+   RebasePointer(Pools, old_base, Base);
    WorkSpace = newSize;
 
    return true;
diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc
index 56716b5..7a5a20c 100644
--- a/apt/apt-pkg/pkgcachegen.cc
+++ b/apt/apt-pkg/pkgcachegen.cc
@@ -26,6 +26,7 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/rebase_pointer.h>
 
 #include <apti18n.h>
 
@@ -116,11 +117,11 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
 
    Cache.ReMap(false);
 
-   CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap;
+   RebasePointer(CurrentFile, oldMap, newMap);
 
    for (size_t i = 0; i < _count(UniqHash); ++i)
       if (UniqHash[i] != 0)
-         UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap;
+         RebasePointer(UniqHash[i], oldMap, newMap);
 
    for (auto i = Dynamic<pkgCache::PkgIterator>::toReMap.begin();
         i != Dynamic<pkgCache::PkgIterator>::toReMap.end(); ++i)
@@ -269,11 +270,8 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
 	 continue;
       }      
 
-      if (oldMap != Map.Data())
-      {
-         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
-         oldMap = Map.Data();
-      }
+      RebasePointer(Last, oldMap, Map.Data());
+      oldMap = Map.Data();
 
       // Skip to the end of the same version set.
       if (Res == 0)
@@ -296,8 +294,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
          return _error->Error(_("Error occurred while processing %s (NewVersion%d)"),
                               PackageName.c_str(), 1);
 
-      if (oldMap != Map.Data())
-         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+      RebasePointer(Last, oldMap, Map.Data());
       *Last = *verindex;
 
       Ver->ParentPkg = Pkg.Index();
@@ -604,8 +601,9 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
       for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
 	 OldDepLast = &D->NextDepends;
       OldDepVer = Ver;
-   } else if (oldMap != Owner->Map.Data())
-      OldDepLast += (map_ptrloc*) Owner->Map.Data() - (map_ptrloc*) oldMap;
+   } else {
+      RebasePointer(OldDepLast, oldMap, Owner->Map.Data());
+   }
 
    // Is it a file dependency?
    if (PackageName[0] == '/')
@@ -745,11 +743,8 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
    if ((!Item) || (!idxString))
       return std::experimental::optional<map_ptrloc>();
 
-   if (oldMap != Map.Data())
-   {
-      Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
-      I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap;
-   }
+   RebasePointer(Last, oldMap, Map.Data());
+   RebasePointer(I, oldMap, Map.Data());
 
    *Last = *Item;
 
diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
new file mode 100644
index 0000000..2bbabea
--- /dev/null
+++ b/apt/apt-pkg/rebase_pointer.h
@@ -0,0 +1,25 @@
+#ifndef PKGLIB_REBASE_POINTER_H
+#define PKGLIB_REBASE_POINTER_H
+
+template <class T>
+static inline T*
+GetRebasedPointer(T*, const void *, const void *)
+__attribute__((__warn_unused_result__));
+
+template <class T>
+static inline T*
+GetRebasedPointer(T* ptr, const void *old_base, const void *new_base)
+{
+	// uintptr_t is a type with well-defined integer overflow semantics
+	uintptr_t diff = (uintptr_t) new_base - (uintptr_t) old_base;
+	return (T*) ((uintptr_t) ptr + diff);
+}
+
+template <class T>
+static inline void
+RebasePointer(T* &ptr, const void *old_base, const void *new_base)
+{
+	ptr = GetRebasedPointer(ptr, old_base, new_base);
+}
+
+#endif
diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc b/apt/apt-pkg/rpm/rpmlistparser.cc
index 9b2e9ad..4aeb937 100644
--- a/apt/apt-pkg/rpm/rpmlistparser.cc
+++ b/apt/apt-pkg/rpm/rpmlistparser.cc
@@ -25,6 +25,7 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/crc-16.h>
 #include <apt-pkg/tagfile.h>
+#include <apt-pkg/rebase_pointer.h>
 
 #include <apti18n.h>
 
@@ -56,7 +57,7 @@ rpmListParser::rpmListParser(RPMHandler *Handler)
 
          for (auto iter: *SeenPackages)
          {
-            tmp.insert(iter + (static_cast<const char *>(newMap) - static_cast<const char *>(oldMap)));
+            tmp.insert(GetRebasedPointer(iter, oldMap, newMap));
          }
 
          SeenPackages->swap(tmp);
-- 
ldv


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-09  7:08         ` Aleksei Nikiforov
@ 2019-12-10  0:07           ` Dmitry V. Levin
  2019-12-10  8:18             ` Aleksei Nikiforov
  0 siblings, 1 reply; 34+ messages in thread
From: Dmitry V. Levin @ 2019-12-10  0:07 UTC (permalink / raw)
  To: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 3719 bytes --]

On Mon, Dec 09, 2019 at 10:08:42AM +0300, Aleksei Nikiforov wrote:
> 09.12.2019 2:21, Dmitry V. Levin пишет:
> > On Fri, Dec 06, 2019 at 06:36:55PM +0300, Aleksei Nikiforov wrote:
> > [...]
> >> @@ -85,11 +87,11 @@ class pkgCache::PkgIterator
> >>      inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
> >>      OkState State() const;
> >>   
> >> -   void ReMap(void const * const oldMap, void const * const newMap)
> >> +   void ReMap(void *oldMap, void *newMap)
> > 
> > Is there any particular reason for stripping const here and in other
> > similar places?
> 
> Yes, it's needed due to issues emerging from mixing const and non-const 
> pointers with new and allegedly more proper way of calculating rebased 
> pointers.

Sorry, I don't find this argument convincing.
I have experienced no const issues in my version of this fix.

> > [...]
> >> @@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
> >>         Pool* oldPools = Pools;
> >>         auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
> >>         if (Pools != oldPools)
> >> -         I += Pools - oldPools;
> >> +         I = RebasePointer(I, oldPools, Pools);
> >>   
> >>         // Does the allocation failed ?
> >>         if (!idxResult)
> > 
> > In my patch RebasePointer invocation was after the idxResult check,
> > not before the check.
> 
> Theoretically, order here might be important. In practice, it doesn't 
> matter.

We normally try to write code that raises less questions.

> > By the way, in this and other similar cases,
> > is there any reason for "Pools != oldPools" check?
> > Is RebasePointer incapable of handling this, or is it an optimization?
> > 
> 
> It's just an optimization, it may be removed.

OK

> > [...]
> >> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
> >> new file mode 100644
> >> index 0000000..f6b3c15
> >> --- /dev/null
> >> +++ b/apt/apt-pkg/rebase_pointer.h
> >> @@ -0,0 +1,16 @@
> >> +#ifndef PKGLIB_REBASE_POINTER_H
> >> +#define PKGLIB_REBASE_POINTER_H
> >> +
> >> +template <typename T>
> >> +static inline T* RebasePointer(T *ptr, void *old_base, void *new_base)
> >> +{
> >> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(old_base)));
> >> +}
> >> +
> >> +template <typename T>
> >> +static inline const T* RebasePointer(const T *ptr, void *old_base, void *new_base)
> >> +{
> >> +   return reinterpret_cast<const T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<const char*>(ptr) - reinterpret_cast<char*>(old_base)));
> >> +}
> >> +
> >> +#endif
> > 
> > Do we really need two templates here?
> 
> Yes, second template with const ptr is needed for 
> rpmListParser::rpmListParser from rpmlistparser.cc.
> 
> Variable SeenPackages has type SeenPackagesType, which is a typedef to 
> std::set<const char*,cstr_lt_pred>. Thus, elements are 'const char*', 
> and either it should be const-casted to 'char*', which is ugly, or 
> const-correctness should be achieved some other way, for example by 
> getting rid of unimportant const qualifiers like in my changes.
> 
> And first template is needed for every other case with non-const ptr.

To be honest, I find my October version of the fix easier to read.

Since all users of RebasePointer except rpmListParser use it in a form of
	ptr = RebasePointer(ptr, old_base, new_base);
I find it more natural when RebasePointer updates the pointer,
so one can write
	RebasePointer(ptr, old_base, new_base);
instead.

OK, I posted my version of the fix.


-- 
ldv

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-10  0:07           ` Dmitry V. Levin
@ 2019-12-10  8:18             ` Aleksei Nikiforov
  2019-12-10 10:20               ` Dmitry V. Levin
  0 siblings, 1 reply; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-10  8:18 UTC (permalink / raw)
  To: devel

10.12.2019 3:07, Dmitry V. Levin пишет:
> On Mon, Dec 09, 2019 at 10:08:42AM +0300, Aleksei Nikiforov wrote:
>> 09.12.2019 2:21, Dmitry V. Levin пишет:
>>> On Fri, Dec 06, 2019 at 06:36:55PM +0300, Aleksei Nikiforov wrote:
>>> [...]
>>>> @@ -85,11 +87,11 @@ class pkgCache::PkgIterator
>>>>       inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
>>>>       OkState State() const;
>>>>    
>>>> -   void ReMap(void const * const oldMap, void const * const newMap)
>>>> +   void ReMap(void *oldMap, void *newMap)
>>>
>>> Is there any particular reason for stripping const here and in other
>>> similar places?
>>
>> Yes, it's needed due to issues emerging from mixing const and non-const
>> pointers with new and allegedly more proper way of calculating rebased
>> pointers.
> 
> Sorry, I don't find this argument convincing.
> I have experienced no const issues in my version of this fix.
> 

Your version is using C-style casts in C++ code. Of course, I could use 
C-style casts or const_cast-s too to work around const correctness 
issues (i.e. to just hide these issues), and it'd work like your 
version. But I'd like to remind you that APT is C++ project, not a C 
project. What might be ok for C is sometimes a dirty ugly hack in modern 
C++.

>>> [...]
>>>> @@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
>>>>          Pool* oldPools = Pools;
>>>>          auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
>>>>          if (Pools != oldPools)
>>>> -         I += Pools - oldPools;
>>>> +         I = RebasePointer(I, oldPools, Pools);
>>>>    
>>>>          // Does the allocation failed ?
>>>>          if (!idxResult)
>>>
>>> In my patch RebasePointer invocation was after the idxResult check,
>>> not before the check.
>>
>> Theoretically, order here might be important. In practice, it doesn't
>> matter.
> 
> We normally try to write code that raises less questions.
> 

In that case it's better to keep order from my patch, isn't it? 
Practically it's fine either way, but theoretically that order is superior.

>>> By the way, in this and other similar cases,
>>> is there any reason for "Pools != oldPools" check?
>>> Is RebasePointer incapable of handling this, or is it an optimization?
>>>
>>
>> It's just an optimization, it may be removed.
> 
> OK
> 
>>> [...]
>>>> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
>>>> new file mode 100644
>>>> index 0000000..f6b3c15
>>>> --- /dev/null
>>>> +++ b/apt/apt-pkg/rebase_pointer.h
>>>> @@ -0,0 +1,16 @@
>>>> +#ifndef PKGLIB_REBASE_POINTER_H
>>>> +#define PKGLIB_REBASE_POINTER_H
>>>> +
>>>> +template <typename T>
>>>> +static inline T* RebasePointer(T *ptr, void *old_base, void *new_base)
>>>> +{
>>>> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(old_base)));
>>>> +}
>>>> +
>>>> +template <typename T>
>>>> +static inline const T* RebasePointer(const T *ptr, void *old_base, void *new_base)
>>>> +{
>>>> +   return reinterpret_cast<const T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<const char*>(ptr) - reinterpret_cast<char*>(old_base)));
>>>> +}
>>>> +
>>>> +#endif
>>>
>>> Do we really need two templates here?
>>
>> Yes, second template with const ptr is needed for
>> rpmListParser::rpmListParser from rpmlistparser.cc.
>>
>> Variable SeenPackages has type SeenPackagesType, which is a typedef to
>> std::set<const char*,cstr_lt_pred>. Thus, elements are 'const char*',
>> and either it should be const-casted to 'char*', which is ugly, or
>> const-correctness should be achieved some other way, for example by
>> getting rid of unimportant const qualifiers like in my changes.
>>
>> And first template is needed for every other case with non-const ptr.
> 
> To be honest, I find my October version of the fix easier to read.
> 
> Since all users of RebasePointer except rpmListParser use it in a form of
> 	ptr = RebasePointer(ptr, old_base, new_base);
> I find it more natural when RebasePointer updates the pointer,
> so one can write
> 	RebasePointer(ptr, old_base, new_base);
> instead.
> 
> OK, I posted my version of the fix.
> 

And it's opposite for me. I prefer to explicitly see when variable is 
changed. And for all calls it looks exactly same: no matter how it's 
used, new pointer is returned from function as a result of function. 
Interface uniformity, obviousness and predictability is important.

> 
> 
> _______________________________________________
> Devel mailing list
> Devel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel
> 


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH apt 3/3] Fix UB in pointer arithmetic
  2019-12-09 23:56     ` [devel] [PATCH apt 3/3] Fix UB in pointer arithmetic Dmitry V. Levin
@ 2019-12-10  8:18       ` Aleksei Nikiforov
  0 siblings, 0 replies; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-10  8:18 UTC (permalink / raw)
  To: devel

10.12.2019 2:56, Dmitry V. Levin пишет:
> Commit 6d5e6a689d07de8feef2cbecb24bc42d5994861b aka 0.5.15lorg2-alt70~9
> among other changes introduced UB in pointer arithmetic by casting raw
> pointers to specific types.
> 
> Fix this by introducing two helpers for rebasing pointers in a safe way.
> 
> Co-developed-by: Aleksei Nikiforov <darktemplar@altlinux.org>

This line is not true. I didn't participate in creation of this version 
of patch. Please remove it.

> Fixes: 6d5e6a68 ("apt-pkg/pkgcachegen.{cc,h} changes")
> ---
>   apt/apt-pkg/Makefile.am          |  1 +
>   apt/apt-pkg/cacheiterators.h     | 14 ++++++++------
>   apt/apt-pkg/contrib/mmap.cc      |  8 ++++----
>   apt/apt-pkg/pkgcachegen.cc       | 27 +++++++++++----------------
>   apt/apt-pkg/rebase_pointer.h     | 25 +++++++++++++++++++++++++
>   apt/apt-pkg/rpm/rpmlistparser.cc |  3 ++-
>   6 files changed, 51 insertions(+), 27 deletions(-)
>   create mode 100644 apt/apt-pkg/rebase_pointer.h
> 
> diff --git a/apt/apt-pkg/Makefile.am b/apt/apt-pkg/Makefile.am
> index 4c0d234..d038d01 100644
> --- a/apt/apt-pkg/Makefile.am
> +++ b/apt/apt-pkg/Makefile.am
> @@ -94,6 +94,7 @@ libapt_pkg_la_SOURCES = \
>   	pkgsystem.h \
>   	policy.cc \
>   	policy.h \
> +	rebase_pointer.h \
>   	repository.cc \
>   	repository.h \
>   	scopeexit.h \
> diff --git a/apt/apt-pkg/cacheiterators.h b/apt/apt-pkg/cacheiterators.h
> index 9dffeb3..3c60cb8 100644
> --- a/apt/apt-pkg/cacheiterators.h
> +++ b/apt/apt-pkg/cacheiterators.h
> @@ -34,6 +34,8 @@
>   #pragma interface "apt-pkg/cacheiterators.h"
>   #endif
>   
> +#include <apt-pkg/rebase_pointer.h>
> +
>   // Package Iterator
>   class pkgCache::PkgIterator
>   {
> @@ -87,7 +89,7 @@ class pkgCache::PkgIterator
>      {
>         if (Owner == 0 || Pkg == 0)
>            return;
> -      Pkg += static_cast<Package const *>(newMap) - static_cast<Package const *>(oldMap);
> +      RebasePointer(Pkg, oldMap, newMap);
>      }
>   
>      // Constructors
> @@ -149,7 +151,7 @@ class pkgCache::VerIterator
>      {
>         if (Owner == 0 || Ver == 0)
>            return;
> -      Ver += static_cast<Version const *>(newMap) - static_cast<Version const *>(oldMap);
> +      RebasePointer(Ver, oldMap, newMap);
>      }
>   
>      inline VerIterator() : Ver(0), Owner(0) {};
> @@ -222,7 +224,7 @@ class pkgCache::DepIterator
>      {
>         if (Owner == 0 || Dep == 0)
>            return;
> -      Dep += static_cast<Dependency const *>(newMap) - static_cast<Dependency const *>(oldMap);
> +      RebasePointer(Dep, oldMap, newMap);
>      }
>   
>      inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) :
> @@ -281,7 +283,7 @@ class pkgCache::PrvIterator
>      {
>         if (Owner == 0 || Prv == 0)
>            return;
> -      Prv += static_cast<Provides const *>(newMap) - static_cast<Provides const *>(oldMap);
> +      RebasePointer(Prv, oldMap, newMap);
>      }
>   
>      inline PrvIterator() : Prv(0), Type(PrvVer), Owner(0)  {};
> @@ -344,7 +346,7 @@ class pkgCache::PkgFileIterator
>      {
>         if (Owner == 0 || File == 0)
>            return;
> -      File += static_cast<PackageFile const *>(newMap) - static_cast<PackageFile const *>(oldMap);
> +      RebasePointer(File, oldMap, newMap);
>      }
>   
>      // Constructors
> @@ -385,7 +387,7 @@ class pkgCache::VerFileIterator
>      {
>         if (Owner == 0 || FileP == 0)
>            return;
> -      FileP += static_cast<VerFile const *>(newMap) - static_cast<VerFile const *>(oldMap);
> +      RebasePointer(FileP, oldMap, newMap);
>      }
>   
>      inline VerFileIterator() : Owner(0), FileP(0) {};
> diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
> index 2064fc4..779d7a6 100644
> --- a/apt/apt-pkg/contrib/mmap.cc
> +++ b/apt/apt-pkg/contrib/mmap.cc
> @@ -30,6 +30,7 @@
>   #include <apt-pkg/configuration.h>
>   #include <apt-pkg/mmap.h>
>   #include <apt-pkg/error.h>
> +#include <apt-pkg/rebase_pointer.h>
>   
>   #include <apti18n.h>
>   
> @@ -285,13 +286,12 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
>         I->Count = size/ItemSize;
>         Pool* oldPools = Pools;
>         auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
> -      if (Pools != oldPools)
> -         I += Pools - oldPools;
>   
>         // Does the allocation failed ?
>         if (!idxResult)
>            return idxResult;
>   
> +      RebasePointer(I, oldPools, Pools);
>         Result = *idxResult;
>         I->Start = Result;
>      }
> @@ -356,7 +356,7 @@ bool DynamicMMap::Grow(unsigned long long size)
>         Fd->Write(&C,sizeof(C));
>      }
>   
> -   unsigned long const poolOffset = Pools - ((Pool*) Base);
> +   const void *old_base = Base;
>   
>      if (Fd != 0)
>      {
> @@ -393,7 +393,7 @@ bool DynamicMMap::Grow(unsigned long long size)
>         memset((char*)Base + WorkSpace, 0, newSize - WorkSpace);
>      }
>   
> -   Pools = (Pool*) Base + poolOffset;
> +   RebasePointer(Pools, old_base, Base);
>      WorkSpace = newSize;
>   
>      return true;
> diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc
> index 56716b5..7a5a20c 100644
> --- a/apt/apt-pkg/pkgcachegen.cc
> +++ b/apt/apt-pkg/pkgcachegen.cc
> @@ -26,6 +26,7 @@
>   #include <apt-pkg/strutl.h>
>   #include <apt-pkg/sptr.h>
>   #include <apt-pkg/pkgsystem.h>
> +#include <apt-pkg/rebase_pointer.h>
>   
>   #include <apti18n.h>
>   
> @@ -116,11 +117,11 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
>   
>      Cache.ReMap(false);
>   
> -   CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap;
> +   RebasePointer(CurrentFile, oldMap, newMap);
>   
>      for (size_t i = 0; i < _count(UniqHash); ++i)
>         if (UniqHash[i] != 0)
> -         UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap;
> +         RebasePointer(UniqHash[i], oldMap, newMap);
>   
>      for (auto i = Dynamic<pkgCache::PkgIterator>::toReMap.begin();
>           i != Dynamic<pkgCache::PkgIterator>::toReMap.end(); ++i)
> @@ -269,11 +270,8 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>   	 continue;
>         }
>   
> -      if (oldMap != Map.Data())
> -      {
> -         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
> -         oldMap = Map.Data();
> -      }
> +      RebasePointer(Last, oldMap, Map.Data());
> +      oldMap = Map.Data();
>   
>         // Skip to the end of the same version set.
>         if (Res == 0)
> @@ -296,8 +294,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>            return _error->Error(_("Error occurred while processing %s (NewVersion%d)"),
>                                 PackageName.c_str(), 1);
>   
> -      if (oldMap != Map.Data())
> -         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
> +      RebasePointer(Last, oldMap, Map.Data());
>         *Last = *verindex;
>   
>         Ver->ParentPkg = Pkg.Index();
> @@ -604,8 +601,9 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
>         for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
>   	 OldDepLast = &D->NextDepends;
>         OldDepVer = Ver;
> -   } else if (oldMap != Owner->Map.Data())
> -      OldDepLast += (map_ptrloc*) Owner->Map.Data() - (map_ptrloc*) oldMap;
> +   } else {
> +      RebasePointer(OldDepLast, oldMap, Owner->Map.Data());
> +   }
>   
>      // Is it a file dependency?
>      if (PackageName[0] == '/')
> @@ -745,11 +743,8 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
>      if ((!Item) || (!idxString))
>         return std::experimental::optional<map_ptrloc>();
>   
> -   if (oldMap != Map.Data())
> -   {
> -      Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
> -      I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap;
> -   }
> +   RebasePointer(Last, oldMap, Map.Data());
> +   RebasePointer(I, oldMap, Map.Data());
>   
>      *Last = *Item;
>   
> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
> new file mode 100644
> index 0000000..2bbabea
> --- /dev/null
> +++ b/apt/apt-pkg/rebase_pointer.h
> @@ -0,0 +1,25 @@
> +#ifndef PKGLIB_REBASE_POINTER_H
> +#define PKGLIB_REBASE_POINTER_H
> +
> +template <class T>
> +static inline T*
> +GetRebasedPointer(T*, const void *, const void *)
> +__attribute__((__warn_unused_result__));
> +
> +template <class T>
> +static inline T*
> +GetRebasedPointer(T* ptr, const void *old_base, const void *new_base)
> +{
> +	// uintptr_t is a type with well-defined integer overflow semantics
> +	uintptr_t diff = (uintptr_t) new_base - (uintptr_t) old_base;
> +	return (T*) ((uintptr_t) ptr + diff);
> +}
> +
> +template <class T>
> +static inline void
> +RebasePointer(T* &ptr, const void *old_base, const void *new_base)
> +{
> +	ptr = GetRebasedPointer(ptr, old_base, new_base);
> +}
> +
> +#endif
> diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc b/apt/apt-pkg/rpm/rpmlistparser.cc
> index 9b2e9ad..4aeb937 100644
> --- a/apt/apt-pkg/rpm/rpmlistparser.cc
> +++ b/apt/apt-pkg/rpm/rpmlistparser.cc
> @@ -25,6 +25,7 @@
>   #include <apt-pkg/strutl.h>
>   #include <apt-pkg/crc-16.h>
>   #include <apt-pkg/tagfile.h>
> +#include <apt-pkg/rebase_pointer.h>
>   
>   #include <apti18n.h>
>   
> @@ -56,7 +57,7 @@ rpmListParser::rpmListParser(RPMHandler *Handler)
>   
>            for (auto iter: *SeenPackages)
>            {
> -            tmp.insert(iter + (static_cast<const char *>(newMap) - static_cast<const char *>(oldMap)));
> +            tmp.insert(GetRebasedPointer(iter, oldMap, newMap));
>            }
>   
>            SeenPackages->swap(tmp);
> 


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-10  8:18             ` Aleksei Nikiforov
@ 2019-12-10 10:20               ` Dmitry V. Levin
  2019-12-10 10:58                 ` Aleksei Nikiforov
  0 siblings, 1 reply; 34+ messages in thread
From: Dmitry V. Levin @ 2019-12-10 10:20 UTC (permalink / raw)
  To: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 5454 bytes --]

On Tue, Dec 10, 2019 at 11:18:06AM +0300, Aleksei Nikiforov wrote:
> 10.12.2019 3:07, Dmitry V. Levin пишет:
> > On Mon, Dec 09, 2019 at 10:08:42AM +0300, Aleksei Nikiforov wrote:
> >> 09.12.2019 2:21, Dmitry V. Levin пишет:
> >>> On Fri, Dec 06, 2019 at 06:36:55PM +0300, Aleksei Nikiforov wrote:
> >>> [...]
> >>>> @@ -85,11 +87,11 @@ class pkgCache::PkgIterator
> >>>>       inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
> >>>>       OkState State() const;
> >>>>    
> >>>> -   void ReMap(void const * const oldMap, void const * const newMap)
> >>>> +   void ReMap(void *oldMap, void *newMap)
> >>>
> >>> Is there any particular reason for stripping const here and in other
> >>> similar places?
> >>
> >> Yes, it's needed due to issues emerging from mixing const and non-const
> >> pointers with new and allegedly more proper way of calculating rebased
> >> pointers.
> > 
> > Sorry, I don't find this argument convincing.
> > I have experienced no const issues in my version of this fix.
> 
> Your version is using C-style casts in C++ code. Of course, I could use 
> C-style casts or const_cast-s too to work around const correctness 
> issues (i.e. to just hide these issues), and it'd work like your 
> version. But I'd like to remind you that APT is C++ project, not a C 
> project. What might be ok for C is sometimes a dirty ugly hack in modern 
> C++.

Sorry, I don't share you point of view on this matter.
Being a C++ project allows you to use C++ constructs, that's true,
but why do you think it prevents you from using C constructs when
appropriate?

> >>>> @@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
> >>>>          Pool* oldPools = Pools;
> >>>>          auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
> >>>>          if (Pools != oldPools)
> >>>> -         I += Pools - oldPools;
> >>>> +         I = RebasePointer(I, oldPools, Pools);
> >>>>    
> >>>>          // Does the allocation failed ?
> >>>>          if (!idxResult)
> >>>
> >>> In my patch RebasePointer invocation was after the idxResult check,
> >>> not before the check.
> >>
> >> Theoretically, order here might be important. In practice, it doesn't
> >> matter.
> > 
> > We normally try to write code that raises less questions.
> 
> In that case it's better to keep order from my patch, isn't it? 
> Practically it's fine either way, but theoretically that order is superior.

The order in question was introduced by your commit
6d5e6a68 ("apt-pkg/pkgcachegen.{cc,h} changes").

If I was reviewing that commit, this would have been fixed already.

> >>> [...]
> >>>> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
> >>>> new file mode 100644
> >>>> index 0000000..f6b3c15
> >>>> --- /dev/null
> >>>> +++ b/apt/apt-pkg/rebase_pointer.h
> >>>> @@ -0,0 +1,16 @@
> >>>> +#ifndef PKGLIB_REBASE_POINTER_H
> >>>> +#define PKGLIB_REBASE_POINTER_H
> >>>> +
> >>>> +template <typename T>
> >>>> +static inline T* RebasePointer(T *ptr, void *old_base, void *new_base)
> >>>> +{
> >>>> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(old_base)));
> >>>> +}
> >>>> +
> >>>> +template <typename T>
> >>>> +static inline const T* RebasePointer(const T *ptr, void *old_base, void *new_base)
> >>>> +{
> >>>> +   return reinterpret_cast<const T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<const char*>(ptr) - reinterpret_cast<char*>(old_base)));
> >>>> +}
> >>>> +
> >>>> +#endif
> >>>
> >>> Do we really need two templates here?
> >>
> >> Yes, second template with const ptr is needed for
> >> rpmListParser::rpmListParser from rpmlistparser.cc.
> >>
> >> Variable SeenPackages has type SeenPackagesType, which is a typedef to
> >> std::set<const char*,cstr_lt_pred>. Thus, elements are 'const char*',
> >> and either it should be const-casted to 'char*', which is ugly, or
> >> const-correctness should be achieved some other way, for example by
> >> getting rid of unimportant const qualifiers like in my changes.
> >>
> >> And first template is needed for every other case with non-const ptr.
> > 
> > To be honest, I find my October version of the fix easier to read.
> > 
> > Since all users of RebasePointer except rpmListParser use it in a form of
> > 	ptr = RebasePointer(ptr, old_base, new_base);
> > I find it more natural when RebasePointer updates the pointer,
> > so one can write
> > 	RebasePointer(ptr, old_base, new_base);
> > instead.
> > 
> > OK, I posted my version of the fix.
> 
> And it's opposite for me. I prefer to explicitly see when variable is 
> changed. And for all calls it looks exactly same: no matter how it's 
> used, new pointer is returned from function as a result of function. 
> Interface uniformity, obviousness and predictability is important.

What I don't like in your approach is that it's error-prone:
it's very easy to forget the assignment or to assign the result to a wrong
variable.  In fact, I had to use the following regular expression just
to check whether all uses of RebasePointer are correct in that respect:

$ git grep -Fw RebasePointer |grep -v '\<\([[:alpha:]][][[:alnum:]_]*\) = RebasePointer(\1,'

This is surely not the way how things should be done,
neither in C nor in C++.


-- 
ldv

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-10 10:20               ` Dmitry V. Levin
@ 2019-12-10 10:58                 ` Aleksei Nikiforov
  2019-12-10 22:20                   ` Dmitry V. Levin
  0 siblings, 1 reply; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-10 10:58 UTC (permalink / raw)
  To: devel

10.12.2019 13:20, Dmitry V. Levin пишет:
> On Tue, Dec 10, 2019 at 11:18:06AM +0300, Aleksei Nikiforov wrote:
>> 10.12.2019 3:07, Dmitry V. Levin пишет:
>>> On Mon, Dec 09, 2019 at 10:08:42AM +0300, Aleksei Nikiforov wrote:
>>>> 09.12.2019 2:21, Dmitry V. Levin пишет:
>>>>> On Fri, Dec 06, 2019 at 06:36:55PM +0300, Aleksei Nikiforov wrote:
>>>>> [...]
>>>>>> @@ -85,11 +87,11 @@ class pkgCache::PkgIterator
>>>>>>        inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
>>>>>>        OkState State() const;
>>>>>>     
>>>>>> -   void ReMap(void const * const oldMap, void const * const newMap)
>>>>>> +   void ReMap(void *oldMap, void *newMap)
>>>>>
>>>>> Is there any particular reason for stripping const here and in other
>>>>> similar places?
>>>>
>>>> Yes, it's needed due to issues emerging from mixing const and non-const
>>>> pointers with new and allegedly more proper way of calculating rebased
>>>> pointers.
>>>
>>> Sorry, I don't find this argument convincing.
>>> I have experienced no const issues in my version of this fix.
>>
>> Your version is using C-style casts in C++ code. Of course, I could use
>> C-style casts or const_cast-s too to work around const correctness
>> issues (i.e. to just hide these issues), and it'd work like your
>> version. But I'd like to remind you that APT is C++ project, not a C
>> project. What might be ok for C is sometimes a dirty ugly hack in modern
>> C++.
> 
> Sorry, I don't share you point of view on this matter.
> Being a C++ project allows you to use C++ constructs, that's true,
> but why do you think it prevents you from using C constructs when
> appropriate?
> 

I didn't say that something prevents from using C constructs when 
appropriate. I'm saying that these constructs are not appropriate here.

>>>>>> @@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
>>>>>>           Pool* oldPools = Pools;
>>>>>>           auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
>>>>>>           if (Pools != oldPools)
>>>>>> -         I += Pools - oldPools;
>>>>>> +         I = RebasePointer(I, oldPools, Pools);
>>>>>>     
>>>>>>           // Does the allocation failed ?
>>>>>>           if (!idxResult)
>>>>>
>>>>> In my patch RebasePointer invocation was after the idxResult check,
>>>>> not before the check.
>>>>
>>>> Theoretically, order here might be important. In practice, it doesn't
>>>> matter.
>>>
>>> We normally try to write code that raises less questions.
>>
>> In that case it's better to keep order from my patch, isn't it?
>> Practically it's fine either way, but theoretically that order is superior.
> 
> The order in question was introduced by your commit
> 6d5e6a68 ("apt-pkg/pkgcachegen.{cc,h} changes").
> 
> If I was reviewing that commit, this would have been fixed already.
> 

So, do you have any reason why it should be changed?

>>>>> [...]
>>>>>> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
>>>>>> new file mode 100644
>>>>>> index 0000000..f6b3c15
>>>>>> --- /dev/null
>>>>>> +++ b/apt/apt-pkg/rebase_pointer.h
>>>>>> @@ -0,0 +1,16 @@
>>>>>> +#ifndef PKGLIB_REBASE_POINTER_H
>>>>>> +#define PKGLIB_REBASE_POINTER_H
>>>>>> +
>>>>>> +template <typename T>
>>>>>> +static inline T* RebasePointer(T *ptr, void *old_base, void *new_base)
>>>>>> +{
>>>>>> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(old_base)));
>>>>>> +}
>>>>>> +
>>>>>> +template <typename T>
>>>>>> +static inline const T* RebasePointer(const T *ptr, void *old_base, void *new_base)
>>>>>> +{
>>>>>> +   return reinterpret_cast<const T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<const char*>(ptr) - reinterpret_cast<char*>(old_base)));
>>>>>> +}
>>>>>> +
>>>>>> +#endif
>>>>>
>>>>> Do we really need two templates here?
>>>>
>>>> Yes, second template with const ptr is needed for
>>>> rpmListParser::rpmListParser from rpmlistparser.cc.
>>>>
>>>> Variable SeenPackages has type SeenPackagesType, which is a typedef to
>>>> std::set<const char*,cstr_lt_pred>. Thus, elements are 'const char*',
>>>> and either it should be const-casted to 'char*', which is ugly, or
>>>> const-correctness should be achieved some other way, for example by
>>>> getting rid of unimportant const qualifiers like in my changes.
>>>>
>>>> And first template is needed for every other case with non-const ptr.
>>>
>>> To be honest, I find my October version of the fix easier to read.
>>>
>>> Since all users of RebasePointer except rpmListParser use it in a form of
>>> 	ptr = RebasePointer(ptr, old_base, new_base);
>>> I find it more natural when RebasePointer updates the pointer,
>>> so one can write
>>> 	RebasePointer(ptr, old_base, new_base);
>>> instead.
>>>
>>> OK, I posted my version of the fix.
>>
>> And it's opposite for me. I prefer to explicitly see when variable is
>> changed. And for all calls it looks exactly same: no matter how it's
>> used, new pointer is returned from function as a result of function.
>> Interface uniformity, obviousness and predictability is important.
> 
> What I don't like in your approach is that it's error-prone:
> it's very easy to forget the assignment or to assign the result to a wrong
> variable.  In fact, I had to use the following regular expression just
> to check whether all uses of RebasePointer are correct in that respect:
> 
> $ git grep -Fw RebasePointer |grep -v '\<\([[:alpha:]][][[:alnum:]_]*\) = RebasePointer(\1,'
> 
> This is surely not the way how things should be done,
> neither in C nor in C++.
> 
> 

It's also very easy to miss one of places where such pointer 
recalculation is required, but you still want this solution instead of 
generic and centralized memory alignment one. So much for uniformity of 
approaches and solutions.

As for forgetting assignment, your addition of attribute 'warn unused 
result' in your version of patch fixes this potential issue. As for 
other potential issues, they are very far-fetched and synthetic.

> 
> _______________________________________________
> Devel mailing list
> Devel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel
> 


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-10 10:58                 ` Aleksei Nikiforov
@ 2019-12-10 22:20                   ` Dmitry V. Levin
  2019-12-11  7:50                     ` Aleksei Nikiforov
  0 siblings, 1 reply; 34+ messages in thread
From: Dmitry V. Levin @ 2019-12-10 22:20 UTC (permalink / raw)
  To: ALT Devel discussion list

[-- Attachment #1: Type: text/plain, Size: 7161 bytes --]

On Tue, Dec 10, 2019 at 01:58:17PM +0300, Aleksei Nikiforov wrote:
> 10.12.2019 13:20, Dmitry V. Levin пишет:
> > On Tue, Dec 10, 2019 at 11:18:06AM +0300, Aleksei Nikiforov wrote:
> >> 10.12.2019 3:07, Dmitry V. Levin пишет:
> >>> On Mon, Dec 09, 2019 at 10:08:42AM +0300, Aleksei Nikiforov wrote:
> >>>> 09.12.2019 2:21, Dmitry V. Levin пишет:
> >>>>> On Fri, Dec 06, 2019 at 06:36:55PM +0300, Aleksei Nikiforov wrote:
> >>>>> [...]
> >>>>>> @@ -85,11 +87,11 @@ class pkgCache::PkgIterator
> >>>>>>        inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
> >>>>>>        OkState State() const;
> >>>>>>     
> >>>>>> -   void ReMap(void const * const oldMap, void const * const newMap)
> >>>>>> +   void ReMap(void *oldMap, void *newMap)
> >>>>>
> >>>>> Is there any particular reason for stripping const here and in other
> >>>>> similar places?
> >>>>
> >>>> Yes, it's needed due to issues emerging from mixing const and non-const
> >>>> pointers with new and allegedly more proper way of calculating rebased
> >>>> pointers.
> >>>
> >>> Sorry, I don't find this argument convincing.
> >>> I have experienced no const issues in my version of this fix.
> >>
> >> Your version is using C-style casts in C++ code. Of course, I could use
> >> C-style casts or const_cast-s too to work around const correctness
> >> issues (i.e. to just hide these issues), and it'd work like your
> >> version. But I'd like to remind you that APT is C++ project, not a C
> >> project. What might be ok for C is sometimes a dirty ugly hack in modern
> >> C++.
> > 
> > Sorry, I don't share you point of view on this matter.
> > Being a C++ project allows you to use C++ constructs, that's true,
> > but why do you think it prevents you from using C constructs when
> > appropriate?
> 
> I didn't say that something prevents from using C constructs when 
> appropriate. I'm saying that these constructs are not appropriate here.

Why do you think they are not appropriate here?

> >>>>>> @@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
> >>>>>>           Pool* oldPools = Pools;
> >>>>>>           auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
> >>>>>>           if (Pools != oldPools)
> >>>>>> -         I += Pools - oldPools;
> >>>>>> +         I = RebasePointer(I, oldPools, Pools);
> >>>>>>     
> >>>>>>           // Does the allocation failed ?
> >>>>>>           if (!idxResult)
> >>>>>
> >>>>> In my patch RebasePointer invocation was after the idxResult check,
> >>>>> not before the check.
> >>>>
> >>>> Theoretically, order here might be important. In practice, it doesn't
> >>>> matter.
> >>>
> >>> We normally try to write code that raises less questions.
> >>
> >> In that case it's better to keep order from my patch, isn't it?
> >> Practically it's fine either way, but theoretically that order is superior.
> > 
> > The order in question was introduced by your commit
> > 6d5e6a68 ("apt-pkg/pkgcachegen.{cc,h} changes").
> > 
> > If I was reviewing that commit, this would have been fixed already.
> 
> So, do you have any reason why it should be changed?

One of the most basic coding rules says: the return value that needs
checking has to be checked prior to any meaningful use.

> >>>>> [...]
> >>>>>> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
> >>>>>> new file mode 100644
> >>>>>> index 0000000..f6b3c15
> >>>>>> --- /dev/null
> >>>>>> +++ b/apt/apt-pkg/rebase_pointer.h
> >>>>>> @@ -0,0 +1,16 @@
> >>>>>> +#ifndef PKGLIB_REBASE_POINTER_H
> >>>>>> +#define PKGLIB_REBASE_POINTER_H
> >>>>>> +
> >>>>>> +template <typename T>
> >>>>>> +static inline T* RebasePointer(T *ptr, void *old_base, void *new_base)
> >>>>>> +{
> >>>>>> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(old_base)));
> >>>>>> +}
> >>>>>> +
> >>>>>> +template <typename T>
> >>>>>> +static inline const T* RebasePointer(const T *ptr, void *old_base, void *new_base)
> >>>>>> +{
> >>>>>> +   return reinterpret_cast<const T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<const char*>(ptr) - reinterpret_cast<char*>(old_base)));
> >>>>>> +}
> >>>>>> +
> >>>>>> +#endif
> >>>>>
> >>>>> Do we really need two templates here?
> >>>>
> >>>> Yes, second template with const ptr is needed for
> >>>> rpmListParser::rpmListParser from rpmlistparser.cc.
> >>>>
> >>>> Variable SeenPackages has type SeenPackagesType, which is a typedef to
> >>>> std::set<const char*,cstr_lt_pred>. Thus, elements are 'const char*',
> >>>> and either it should be const-casted to 'char*', which is ugly, or
> >>>> const-correctness should be achieved some other way, for example by
> >>>> getting rid of unimportant const qualifiers like in my changes.
> >>>>
> >>>> And first template is needed for every other case with non-const ptr.
> >>>
> >>> To be honest, I find my October version of the fix easier to read.
> >>>
> >>> Since all users of RebasePointer except rpmListParser use it in a form of
> >>> 	ptr = RebasePointer(ptr, old_base, new_base);
> >>> I find it more natural when RebasePointer updates the pointer,
> >>> so one can write
> >>> 	RebasePointer(ptr, old_base, new_base);
> >>> instead.
> >>>
> >>> OK, I posted my version of the fix.
> >>
> >> And it's opposite for me. I prefer to explicitly see when variable is
> >> changed. And for all calls it looks exactly same: no matter how it's
> >> used, new pointer is returned from function as a result of function.
> >> Interface uniformity, obviousness and predictability is important.
> > 
> > What I don't like in your approach is that it's error-prone:
> > it's very easy to forget the assignment or to assign the result to a wrong
> > variable.  In fact, I had to use the following regular expression just
> > to check whether all uses of RebasePointer are correct in that respect:
> > 
> > $ git grep -Fw RebasePointer |grep -v '\<\([[:alpha:]][][[:alnum:]_]*\) = RebasePointer(\1,'
> > 
> > This is surely not the way how things should be done,
> > neither in C nor in C++.
> 
> It's also very easy to miss one of places where such pointer 
> recalculation is required,

There must be a way to exclude this possibility.

> but you still want this solution instead of 
> generic and centralized memory alignment one.

The approach you mentioned is definitely wasteful,
but it's by no means generic or centralized.

> So much for uniformity of approaches and solutions.
> 
> As for forgetting assignment, your addition of attribute 'warn unused 
> result' in your version of patch fixes this potential issue.

Unfortunately, warn_unused_result attribute does not fix anything yet
because it's too easy to miss a new warning among several hundreds of
already existing warnings.  This might help someday in the future when
the whole codebase is ready for -Werror.

> As for other potential issues, they are very far-fetched and synthetic.

Well, I don't think so. :)


-- 
ldv

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-10 22:20                   ` Dmitry V. Levin
@ 2019-12-11  7:50                     ` Aleksei Nikiforov
  2019-12-12 19:43                       ` Andrey Savchenko
  0 siblings, 1 reply; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-11  7:50 UTC (permalink / raw)
  To: devel

11.12.2019 1:20, Dmitry V. Levin пишет:
> On Tue, Dec 10, 2019 at 01:58:17PM +0300, Aleksei Nikiforov wrote:
>> 10.12.2019 13:20, Dmitry V. Levin пишет:
>>> On Tue, Dec 10, 2019 at 11:18:06AM +0300, Aleksei Nikiforov wrote:
>>>> 10.12.2019 3:07, Dmitry V. Levin пишет:
>>>>> On Mon, Dec 09, 2019 at 10:08:42AM +0300, Aleksei Nikiforov wrote:
>>>>>> 09.12.2019 2:21, Dmitry V. Levin пишет:
>>>>>>> On Fri, Dec 06, 2019 at 06:36:55PM +0300, Aleksei Nikiforov wrote:
>>>>>>> [...]
>>>>>>>> @@ -85,11 +87,11 @@ class pkgCache::PkgIterator
>>>>>>>>         inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
>>>>>>>>         OkState State() const;
>>>>>>>>      
>>>>>>>> -   void ReMap(void const * const oldMap, void const * const newMap)
>>>>>>>> +   void ReMap(void *oldMap, void *newMap)
>>>>>>>
>>>>>>> Is there any particular reason for stripping const here and in other
>>>>>>> similar places?
>>>>>>
>>>>>> Yes, it's needed due to issues emerging from mixing const and non-const
>>>>>> pointers with new and allegedly more proper way of calculating rebased
>>>>>> pointers.
>>>>>
>>>>> Sorry, I don't find this argument convincing.
>>>>> I have experienced no const issues in my version of this fix.
>>>>
>>>> Your version is using C-style casts in C++ code. Of course, I could use
>>>> C-style casts or const_cast-s too to work around const correctness
>>>> issues (i.e. to just hide these issues), and it'd work like your
>>>> version. But I'd like to remind you that APT is C++ project, not a C
>>>> project. What might be ok for C is sometimes a dirty ugly hack in modern
>>>> C++.
>>>
>>> Sorry, I don't share you point of view on this matter.
>>> Being a C++ project allows you to use C++ constructs, that's true,
>>> but why do you think it prevents you from using C constructs when
>>> appropriate?
>>
>> I didn't say that something prevents from using C constructs when
>> appropriate. I'm saying that these constructs are not appropriate here.
> 
> Why do you think they are not appropriate here?
> 

In good C++ code there is no place for const_cast. Maybe there are some 
exceptions to it, but they have to be justified. It doesn't matter that 
you are hiding it behind C-style cast.

>>>>>>>> @@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
>>>>>>>>            Pool* oldPools = Pools;
>>>>>>>>            auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
>>>>>>>>            if (Pools != oldPools)
>>>>>>>> -         I += Pools - oldPools;
>>>>>>>> +         I = RebasePointer(I, oldPools, Pools);
>>>>>>>>      
>>>>>>>>            // Does the allocation failed ?
>>>>>>>>            if (!idxResult)
>>>>>>>
>>>>>>> In my patch RebasePointer invocation was after the idxResult check,
>>>>>>> not before the check.
>>>>>>
>>>>>> Theoretically, order here might be important. In practice, it doesn't
>>>>>> matter.
>>>>>
>>>>> We normally try to write code that raises less questions.
>>>>
>>>> In that case it's better to keep order from my patch, isn't it?
>>>> Practically it's fine either way, but theoretically that order is superior.
>>>
>>> The order in question was introduced by your commit
>>> 6d5e6a68 ("apt-pkg/pkgcachegen.{cc,h} changes").
>>>
>>> If I was reviewing that commit, this would have been fixed already.
>>
>> So, do you have any reason why it should be changed?
> 
> One of the most basic coding rules says: the return value that needs
> checking has to be checked prior to any meaningful use.
> 

Ok, considering this rule, looks good.

>>>>>>> [...]
>>>>>>>> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
>>>>>>>> new file mode 100644
>>>>>>>> index 0000000..f6b3c15
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/apt/apt-pkg/rebase_pointer.h
>>>>>>>> @@ -0,0 +1,16 @@
>>>>>>>> +#ifndef PKGLIB_REBASE_POINTER_H
>>>>>>>> +#define PKGLIB_REBASE_POINTER_H
>>>>>>>> +
>>>>>>>> +template <typename T>
>>>>>>>> +static inline T* RebasePointer(T *ptr, void *old_base, void *new_base)
>>>>>>>> +{
>>>>>>>> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(old_base)));
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +template <typename T>
>>>>>>>> +static inline const T* RebasePointer(const T *ptr, void *old_base, void *new_base)
>>>>>>>> +{
>>>>>>>> +   return reinterpret_cast<const T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<const char*>(ptr) - reinterpret_cast<char*>(old_base)));
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +#endif
>>>>>>>
>>>>>>> Do we really need two templates here?
>>>>>>
>>>>>> Yes, second template with const ptr is needed for
>>>>>> rpmListParser::rpmListParser from rpmlistparser.cc.
>>>>>>
>>>>>> Variable SeenPackages has type SeenPackagesType, which is a typedef to
>>>>>> std::set<const char*,cstr_lt_pred>. Thus, elements are 'const char*',
>>>>>> and either it should be const-casted to 'char*', which is ugly, or
>>>>>> const-correctness should be achieved some other way, for example by
>>>>>> getting rid of unimportant const qualifiers like in my changes.
>>>>>>
>>>>>> And first template is needed for every other case with non-const ptr.
>>>>>
>>>>> To be honest, I find my October version of the fix easier to read.
>>>>>
>>>>> Since all users of RebasePointer except rpmListParser use it in a form of
>>>>> 	ptr = RebasePointer(ptr, old_base, new_base);
>>>>> I find it more natural when RebasePointer updates the pointer,
>>>>> so one can write
>>>>> 	RebasePointer(ptr, old_base, new_base);
>>>>> instead.
>>>>>
>>>>> OK, I posted my version of the fix.
>>>>
>>>> And it's opposite for me. I prefer to explicitly see when variable is
>>>> changed. And for all calls it looks exactly same: no matter how it's
>>>> used, new pointer is returned from function as a result of function.
>>>> Interface uniformity, obviousness and predictability is important.
>>>
>>> What I don't like in your approach is that it's error-prone:
>>> it's very easy to forget the assignment or to assign the result to a wrong
>>> variable.  In fact, I had to use the following regular expression just
>>> to check whether all uses of RebasePointer are correct in that respect:
>>>
>>> $ git grep -Fw RebasePointer |grep -v '\<\([[:alpha:]][][[:alnum:]_]*\) = RebasePointer(\1,'
>>>
>>> This is surely not the way how things should be done,
>>> neither in C nor in C++.
>>
>> It's also very easy to miss one of places where such pointer
>> recalculation is required,
> 
> There must be a way to exclude this possibility.
> 
>> but you still want this solution instead of
>> generic and centralized memory alignment one.
> 
> The approach you mentioned is definitely wasteful,
> but it's by no means generic or centralized.
> 

Not as wasteful as you speculated it is. And no, it is centralized and 
generic. It fixes all issues caused by remainders of division being 
non-zero in pointer math.

>> So much for uniformity of approaches and solutions.
>>
>> As for forgetting assignment, your addition of attribute 'warn unused
>> result' in your version of patch fixes this potential issue.
> 
> Unfortunately, warn_unused_result attribute does not fix anything yet
> because it's too easy to miss a new warning among several hundreds of
> already existing warnings.  This might help someday in the future when
> the whole codebase is ready for -Werror.
> 

It's possible to add -Werror=warning-type compiler option to convert 
specific warning into error. You wouldn't miss an error generated by 
compiler, would you? :) Btw, while we're discussing compiler options, 
you can turn errors back into warnings with -Wno-error=warning-type 
compiler option when using -Werror.

>> As for other potential issues, they are very far-fetched and synthetic.
> 
> Well, I don't think so. :)
> 

You can fix that :)

> 
> 
> _______________________________________________
> Devel mailing list
> Devel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel
> 


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-09  6:54         ` Aleksei Nikiforov
@ 2019-12-12 19:20           ` Andrey Savchenko
  2019-12-13  7:58             ` Aleksei Nikiforov
  0 siblings, 1 reply; 34+ messages in thread
From: Andrey Savchenko @ 2019-12-12 19:20 UTC (permalink / raw)
  To: ALT Linux Team development discussions

[-- Attachment #1: Type: text/plain, Size: 18080 bytes --]

On Mon, 9 Dec 2019 09:54:27 +0300 Aleksei Nikiforov wrote:
> 07.12.2019 17:52, Andrey Savchenko пишет:
> > Hi all!
> > 
> > On Fri,  6 Dec 2019 18:36:55 +0300 Aleksei Nikiforov wrote:
> >> This change should fix pointer arithmetic issues for e2k.
> > 
> > This commit message is misleading. Pointer arithmetic is broken on
> > all architectures, but by pure chance in happens to work correctly
> > when gcc is used. On e2k the lcc compiler is used, so problem
> > manifests itself. But this doesn't change the fact that pointer
> > arithmetic was flawed on all architectures.
> > 
> 
> Your first sentence contradicts later ones.

No.

> You just repeated my sentence about issue manifesting on e2k,

No.

> but you did it more verbosely.

Yes.

> Yes, there is a flaw for all architectures, but it manifests only for 
> e2k in practice, thus change fixes it for e2k. So, what's misleading there?

When a commit message is of concern it does matter what is written,
and what was intended but kept behind the scenes is of no
importance.

When one writes "issue A is fixed for B" this implies that A is
B-specific issue, which is false in the discussed case.

> >> ---
> >>   apt/apt-pkg/Makefile.am           |  1 +
> >>   apt/apt-pkg/cacheiterators.h      | 26 ++++++++++++++------------
> >>   apt/apt-pkg/contrib/mmap.cc       |  8 +++++---
> >>   apt/apt-pkg/pkgcachegen.cc        | 29 +++++++++++++++--------------
> >>   apt/apt-pkg/pkgcachegen.h         |  6 +++---
> >>   apt/apt-pkg/rebase_pointer.h      | 16 ++++++++++++++++
> >>   apt/apt-pkg/rpm/rpmlistparser.cc  |  5 +++--
> >>   apt/apt-pkg/rpm/rpmpackagedata.cc |  2 +-
> >>   8 files changed, 58 insertions(+), 35 deletions(-)
> >>   create mode 100644 apt/apt-pkg/rebase_pointer.h
> >>
> >> diff --git a/apt/apt-pkg/Makefile.am b/apt/apt-pkg/Makefile.am
> >> index 4c0d234..d038d01 100644
> >> --- a/apt/apt-pkg/Makefile.am
> >> +++ b/apt/apt-pkg/Makefile.am
> >> @@ -94,6 +94,7 @@ libapt_pkg_la_SOURCES = \
> >>   	pkgsystem.h \
> >>   	policy.cc \
> >>   	policy.h \
> >> +	rebase_pointer.h \
> >>   	repository.cc \
> >>   	repository.h \
> >>   	scopeexit.h \
> >> diff --git a/apt/apt-pkg/cacheiterators.h b/apt/apt-pkg/cacheiterators.h
> >> index a4bf670..118838e 100644
> >> --- a/apt/apt-pkg/cacheiterators.h
> >> +++ b/apt/apt-pkg/cacheiterators.h
> >> @@ -34,6 +34,8 @@
> >>   #pragma interface "apt-pkg/cacheiterators.h"
> >>   #endif
> >>   
> >> +#include <apt-pkg/rebase_pointer.h>
> >> +
> >>   #include <set>
> >>   
> >>   // Package Iterator
> >> @@ -85,11 +87,11 @@ class pkgCache::PkgIterator
> >>      inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
> >>      OkState State() const;
> >>   
> >> -   void ReMap(void const * const oldMap, void const * const newMap)
> >> +   void ReMap(void *oldMap, void *newMap)
> >>      {
> >>         if (Owner == 0 || Pkg == 0)
> >>            return;
> >> -      Pkg += static_cast<Package const *>(newMap) - static_cast<Package const *>(oldMap);
> >> +      Pkg = RebasePointer(Pkg, oldMap, newMap);
> >>      }
> >>   
> >>      // Constructors
> >> @@ -147,11 +149,11 @@ class pkgCache::VerIterator
> >>      bool Automatic() const;
> >>      VerFileIterator NewestFile() const;
> >>   
> >> -   void ReMap(void const * const oldMap, void const * const newMap)
> >> +   void ReMap(void *oldMap, void *newMap)
> >>      {
> >>         if (Owner == 0 || Ver == 0)
> >>            return;
> >> -      Ver += static_cast<Version const *>(newMap) - static_cast<Version const *>(oldMap);
> >> +      Ver = RebasePointer(Ver, oldMap, newMap);
> >>      }
> >>   
> >>      inline VerIterator() : Ver(0), Owner(0) {};
> >> @@ -220,11 +222,11 @@ class pkgCache::DepIterator
> >>      inline const char *CompType() {return Owner->CompType(Dep->CompareOp);};
> >>      inline const char *DepType() {return Owner->DepType(Dep->Type);};
> >>   
> >> -   void ReMap(void const * const oldMap, void const * const newMap)
> >> +   void ReMap(void *oldMap, void *newMap)
> >>      {
> >>         if (Owner == 0 || Dep == 0)
> >>            return;
> >> -      Dep += static_cast<Dependency const *>(newMap) - static_cast<Dependency const *>(oldMap);
> >> +      Dep = RebasePointer(Dep, oldMap, newMap);
> >>      }
> >>   
> >>      inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) :
> >> @@ -279,11 +281,11 @@ class pkgCache::PrvIterator
> >>      inline PkgIterator OwnerPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[Prv->Version].ParentPkg);};
> >>      inline unsigned long long Index() const {return Prv - Owner->ProvideP;};
> >>   
> >> -   void ReMap(void const * const oldMap, void const * const newMap)
> >> +   void ReMap(void *oldMap, void *newMap)
> >>      {
> >>         if (Owner == 0 || Prv == 0)
> >>            return;
> >> -      Prv += static_cast<Provides const *>(newMap) - static_cast<Provides const *>(oldMap);
> >> +      Prv = RebasePointer(Prv, oldMap, newMap);
> >>      }
> >>   
> >>      inline PrvIterator() : Prv(0), Type(PrvVer), Owner(0)  {};
> >> @@ -342,11 +344,11 @@ class pkgCache::PkgFileIterator
> >>      bool IsOk();
> >>      string RelStr();
> >>   
> >> -   void ReMap(void const * const oldMap, void const * const newMap)
> >> +   void ReMap(void *oldMap, void *newMap)
> >>      {
> >>         if (Owner == 0 || File == 0)
> >>            return;
> >> -      File += static_cast<PackageFile const *>(newMap) - static_cast<PackageFile const *>(oldMap);
> >> +      File = RebasePointer(File, oldMap, newMap);
> >>      }
> >>   
> >>      // Constructors
> >> @@ -383,11 +385,11 @@ class pkgCache::VerFileIterator
> >>      inline PkgFileIterator File() const {return PkgFileIterator(*Owner,FileP->File + Owner->PkgFileP);};
> >>      inline unsigned long long Index() const {return FileP - Owner->VerFileP;};
> >>   
> >> -   void ReMap(void const * const oldMap, void const * const newMap)
> >> +   void ReMap(void *oldMap, void *newMap)
> >>      {
> >>         if (Owner == 0 || FileP == 0)
> >>            return;
> >> -      FileP += static_cast<VerFile const *>(newMap) - static_cast<VerFile const *>(oldMap);
> >> +      FileP = RebasePointer(FileP, oldMap, newMap);
> >>      }
> >>   
> >>      inline VerFileIterator() : Owner(0), FileP(0) {};
> >> diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
> >> index cf01be9..35f1a25 100644
> >> --- a/apt/apt-pkg/contrib/mmap.cc
> >> +++ b/apt/apt-pkg/contrib/mmap.cc
> >> @@ -30,6 +30,7 @@
> >>   #include <apt-pkg/configuration.h>
> >>   #include <apt-pkg/mmap.h>
> >>   #include <apt-pkg/error.h>
> >> +#include <apt-pkg/rebase_pointer.h>
> >>   
> >>   #include <apti18n.h>
> >>   
> >> @@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
> >>         Pool* oldPools = Pools;
> >>         auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
> >>         if (Pools != oldPools)
> >> -         I += Pools - oldPools;
> >> +         I = RebasePointer(I, oldPools, Pools);
> >>   
> >>         // Does the allocation failed ?
> >>         if (!idxResult)
> >> @@ -371,7 +372,7 @@ bool DynamicMMap::Grow(unsigned long long size)
> >>         Fd->Write(&C,sizeof(C));
> >>      }
> >>   
> >> -   unsigned long const poolOffset = Pools - ((Pool*) Base);
> >> +   void *old_base = Base;
> >>   
> >>      if (Fd != 0)
> >>      {
> >> @@ -408,7 +409,8 @@ bool DynamicMMap::Grow(unsigned long long size)
> >>         memset((char*)Base + WorkSpace, 0, newSize - WorkSpace);
> >>      }
> >>   
> >> -   Pools = (Pool*) Base + poolOffset;
> >> +   if (Base != old_base)
> >> +      Pools = RebasePointer(Pools, old_base, Base);
> >>      WorkSpace = newSize;
> >>   
> >>      return true;
> >> diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc
> >> index 654c81c..37364e9 100644
> >> --- a/apt/apt-pkg/pkgcachegen.cc
> >> +++ b/apt/apt-pkg/pkgcachegen.cc
> >> @@ -26,6 +26,7 @@
> >>   #include <apt-pkg/strutl.h>
> >>   #include <apt-pkg/sptr.h>
> >>   #include <apt-pkg/pkgsystem.h>
> >> +#include <apt-pkg/rebase_pointer.h>
> >>   
> >>   #include <apti18n.h>
> >>   
> >> @@ -109,18 +110,18 @@ pkgCacheGenerator::~pkgCacheGenerator()
> >>      Map.Sync(0,sizeof(pkgCache::Header));
> >>   }
> >>   									/*}}}*/
> >> -void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newMap)
> >> +void pkgCacheGenerator::ReMap(void *oldMap, void *newMap)
> >>   {
> >>      if (oldMap == newMap)
> >>         return;
> >>   
> >>      Cache.ReMap(false);
> >>   
> >> -   CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap;
> >> +   CurrentFile = RebasePointer(CurrentFile, oldMap, newMap);
> >>   
> >>      for (size_t i = 0; i < _count(UniqHash); ++i)
> >>         if (UniqHash[i] != 0)
> >> -         UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap;
> >> +         UniqHash[i] = RebasePointer(UniqHash[i], oldMap, newMap);
> >>   
> >>      for (auto i = Dynamic<pkgCache::PkgIterator>::toReMap.begin();
> >>           i != Dynamic<pkgCache::PkgIterator>::toReMap.end(); ++i)
> >> @@ -147,7 +148,7 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
> >>   // CacheGenerator::WriteStringInMap					/*{{{*/
> >>   std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(const char *String,
> >>   					unsigned long Len) {
> >> -   void const * const oldMap = Map.Data();
> >> +   void *oldMap = Map.Data();
> >>      const auto index = Map.WriteString(String, Len);
> >>      if (index)
> >>         ReMap(oldMap, Map.Data());
> >> @@ -156,7 +157,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(cons
> >>   									/*}}}*/
> >>   // CacheGenerator::WriteStringInMap					/*{{{*/
> >>   std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(const char *String) {
> >> -   void const * const oldMap = Map.Data();
> >> +   void *oldMap = Map.Data();
> >>      const auto index = Map.WriteString(String);
> >>      if (index)
> >>         ReMap(oldMap, Map.Data());
> >> @@ -164,7 +165,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(cons
> >>   }
> >>   									/*}}}*/
> >>   std::experimental::optional<map_ptrloc> pkgCacheGenerator::AllocateInMap(unsigned long size) {/*{{{*/
> >> -   void const * const oldMap = Map.Data();
> >> +   void *oldMap = Map.Data();
> >>      const auto index = Map.Allocate(size);
> >>      if (index)
> >>         ReMap(oldMap, Map.Data());
> >> @@ -229,7 +230,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
> >>         pkgCache::VerIterator Ver = Pkg.VersionList();
> >>         Dynamic<pkgCache::VerIterator> DynVer(Ver);
> >>         map_ptrloc *Last = &Pkg->VersionList;
> >> -      const void * oldMap = Map.Data();
> >> +      void *oldMap = Map.Data();
> >>         int Res = 1;
> >>         for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
> >>         {
> >> @@ -271,7 +272,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
> >>   
> >>         if (oldMap != Map.Data())
> >>         {
> >> -         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
> >> +         Last = RebasePointer(Last, oldMap, Map.Data());
> >>            oldMap = Map.Data();
> >>         }
> >>   
> >> @@ -297,7 +298,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
> >>                                 PackageName.c_str(), 1);
> >>   
> >>         if (oldMap != Map.Data())
> >> -         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
> >> +         Last = RebasePointer(Last, oldMap, Map.Data());
> >>         *Last = *verindex;
> >>   
> >>         Ver->ParentPkg = Pkg.Index();
> >> @@ -553,7 +554,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
> >>   					       unsigned int Op,
> >>   					       unsigned int Type)
> >>   {
> >> -   void const * const oldMap = Owner->Map.Data();
> >> +   void *oldMap = Owner->Map.Data();
> >>      pkgCache &Cache = Owner->Cache;
> >>      
> >>      // Get a structure
> >> @@ -605,7 +606,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
> >>   	 OldDepLast = &D->NextDepends;
> >>         OldDepVer = Ver;
> >>      } else if (oldMap != Owner->Map.Data())
> >> -      OldDepLast += (map_ptrloc*) Owner->Map.Data() - (map_ptrloc*) oldMap;
> >> +      OldDepLast = RebasePointer(OldDepLast, oldMap, Owner->Map.Data());
> >>   
> >>      // Is it a file dependency?
> >>      if (PackageName[0] == '/')
> >> @@ -739,7 +740,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
> >>      }
> >>      
> >>      // Get a structure
> >> -   void const * const oldMap = Map.Data();
> >> +   void *oldMap = Map.Data();
> >>      const auto Item = AllocateInMap(sizeof(pkgCache::StringItem));
> >>      const auto idxString = WriteStringInMap(S, Size);
> >>      if ((!Item) || (!idxString))
> >> @@ -747,8 +748,8 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
> >>   
> >>      if (oldMap != Map.Data())
> >>      {
> >> -      Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
> >> -      I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap;
> >> +      Last = RebasePointer(Last, oldMap, Map.Data());
> >> +      I = RebasePointer(I, oldMap, Map.Data());
> >>      }
> >>   
> >>      *Last = *Item;
> >> diff --git a/apt/apt-pkg/pkgcachegen.h b/apt/apt-pkg/pkgcachegen.h
> >> index 77075a6..0faf6e1 100644
> >> --- a/apt/apt-pkg/pkgcachegen.h
> >> +++ b/apt/apt-pkg/pkgcachegen.h
> >> @@ -72,7 +72,7 @@ class pkgCacheGenerator
> >>      class DynamicFunction
> >>      {
> >>      public:
> >> -      typedef std::function<void(const void *, const void *)> function;
> >> +      typedef std::function<void(void *, void *)> function;
> >>   
> >>         static std::set<DynamicFunction*> toReMap;
> >>   
> >> @@ -93,7 +93,7 @@ class pkgCacheGenerator
> >>            toReMap.erase(this);
> >>         }
> >>   
> >> -      void call(const void *oldMap, const void *newMap)
> >> +      void call(void *oldMap, void *newMap)
> >>         {
> >>            if (m_function)
> >>               m_function(oldMap, newMap);
> >> @@ -140,7 +140,7 @@ class pkgCacheGenerator
> >>      // CNC:2003-03-18
> >>      inline void ResetFileDeps() {FoundFileDeps = false;};
> >>   
> >> -   void ReMap(void const * const oldMap, void const * const newMap);
> >> +   void ReMap(void *oldMap, void *newMap);
> >>   
> >>      pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress);
> >>      ~pkgCacheGenerator();
> >> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
> >> new file mode 100644
> >> index 0000000..f6b3c15
> >> --- /dev/null
> >> +++ b/apt/apt-pkg/rebase_pointer.h
> >> @@ -0,0 +1,16 @@
> >> +#ifndef PKGLIB_REBASE_POINTER_H
> >> +#define PKGLIB_REBASE_POINTER_H
> >> +
> >> +template <typename T>
> >> +static inline T* RebasePointer(T *ptr, void *old_base, void *new_base)
> >> +{
> >> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(old_base)));
> >> +}
> >> +
> >> +template <typename T>
> >> +static inline const T* RebasePointer(const T *ptr, void *old_base, void *new_base)
> >> +{
> >> +   return reinterpret_cast<const T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<const char*>(ptr) - reinterpret_cast<char*>(old_base)));
> >> +}
> >> +
> >> +#endif
> >> diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc b/apt/apt-pkg/rpm/rpmlistparser.cc
> >> index 9b2e9ad..bd13b99 100644
> >> --- a/apt/apt-pkg/rpm/rpmlistparser.cc
> >> +++ b/apt/apt-pkg/rpm/rpmlistparser.cc
> >> @@ -25,6 +25,7 @@
> >>   #include <apt-pkg/strutl.h>
> >>   #include <apt-pkg/crc-16.h>
> >>   #include <apt-pkg/tagfile.h>
> >> +#include <apt-pkg/rebase_pointer.h>
> >>   
> >>   #include <apti18n.h>
> >>   
> >> @@ -50,13 +51,13 @@ rpmListParser::rpmListParser(RPMHandler *Handler)
> >>      {
> >>         SeenPackages.reset(new SeenPackagesType);
> >>         m_SeenPackagesRealloc.reset(new pkgCacheGenerator::DynamicFunction(
> >> -         [this] (void const *oldMap, void const *newMap)
> >> +         [this] (void *oldMap, void *newMap)
> >>         {
> >>            SeenPackagesType tmp;
> >>   
> >>            for (auto iter: *SeenPackages)
> >>            {
> >> -            tmp.insert(iter + (static_cast<const char *>(newMap) - static_cast<const char *>(oldMap)));
> >> +            tmp.insert(RebasePointer(iter, oldMap, newMap));
> >>            }
> >>   
> >>            SeenPackages->swap(tmp);
> >> diff --git a/apt/apt-pkg/rpm/rpmpackagedata.cc b/apt/apt-pkg/rpm/rpmpackagedata.cc
> >> index 61c15d5..d6c677b 100644
> >> --- a/apt/apt-pkg/rpm/rpmpackagedata.cc
> >> +++ b/apt/apt-pkg/rpm/rpmpackagedata.cc
> >> @@ -23,7 +23,7 @@ RPMPackageData::RPMPackageData()
> >>   #endif
> >>   {
> >>      m_VerMapRealloc.reset(new pkgCacheGenerator::DynamicFunction(
> >> -      [this] (void const *oldMap, void const *newMap)
> >> +      [this] (void *oldMap, void *newMap)
> >>      {
> >>         for (auto iter1 = VerMap.begin(); iter1 != VerMap.end(); ++iter1)
> >>         {
> > 
> > 
> > Best regards,
> > Andrew Savchenko
> > 
> > 
> > _______________________________________________
> > Devel mailing list
> > Devel@lists.altlinux.org
> > https://lists.altlinux.org/mailman/listinfo/devel
> > 
> _______________________________________________
> Devel mailing list
> Devel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel

Best regards,
Andrew Savchenko

[-- Attachment #2: Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-11  7:50                     ` Aleksei Nikiforov
@ 2019-12-12 19:43                       ` Andrey Savchenko
  2019-12-13  8:01                         ` Aleksei Nikiforov
  0 siblings, 1 reply; 34+ messages in thread
From: Andrey Savchenko @ 2019-12-12 19:43 UTC (permalink / raw)
  To: ALT Linux Team development discussions

[-- Attachment #1: Type: text/plain, Size: 3256 bytes --]

On Wed, 11 Dec 2019 10:50:22 +0300 Aleksei Nikiforov wrote:
> 11.12.2019 1:20, Dmitry V. Levin пишет:
> > On Tue, Dec 10, 2019 at 01:58:17PM +0300, Aleksei Nikiforov wrote:
> >> 10.12.2019 13:20, Dmitry V. Levin пишет:
> >>> On Tue, Dec 10, 2019 at 11:18:06AM +0300, Aleksei Nikiforov wrote:
> >>>> 10.12.2019 3:07, Dmitry V. Levin пишет:
> >>>>> On Mon, Dec 09, 2019 at 10:08:42AM +0300, Aleksei Nikiforov wrote:
> >>>>>> 09.12.2019 2:21, Dmitry V. Levin пишет:
> >>>>>>> On Fri, Dec 06, 2019 at 06:36:55PM +0300, Aleksei Nikiforov wrote:
> >>>>>>> [...]
> >>>>>>>> @@ -85,11 +87,11 @@ class pkgCache::PkgIterator
> >>>>>>>>         inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
> >>>>>>>>         OkState State() const;
> >>>>>>>>      
> >>>>>>>> -   void ReMap(void const * const oldMap, void const * const newMap)
> >>>>>>>> +   void ReMap(void *oldMap, void *newMap)
> >>>>>>>
> >>>>>>> Is there any particular reason for stripping const here and in other
> >>>>>>> similar places?
> >>>>>>
> >>>>>> Yes, it's needed due to issues emerging from mixing const and non-const
> >>>>>> pointers with new and allegedly more proper way of calculating rebased
> >>>>>> pointers.
> >>>>>
> >>>>> Sorry, I don't find this argument convincing.
> >>>>> I have experienced no const issues in my version of this fix.
> >>>>
> >>>> Your version is using C-style casts in C++ code. Of course, I could use
> >>>> C-style casts or const_cast-s too to work around const correctness
> >>>> issues (i.e. to just hide these issues), and it'd work like your
> >>>> version. But I'd like to remind you that APT is C++ project, not a C
> >>>> project. What might be ok for C is sometimes a dirty ugly hack in modern
> >>>> C++.
> >>>
> >>> Sorry, I don't share you point of view on this matter.
> >>> Being a C++ project allows you to use C++ constructs, that's true,
> >>> but why do you think it prevents you from using C constructs when
> >>> appropriate?
> >>
> >> I didn't say that something prevents from using C constructs when
> >> appropriate. I'm saying that these constructs are not appropriate here.
> > 
> > Why do you think they are not appropriate here?
> > 
> 
> In good C++ code there is no place for const_cast.

This statement is ungrounded.

> Maybe there are some 
> exceptions to it, but they have to be justified. It doesn't matter that 
> you are hiding it behind C-style cast.

Please read some good book on C++ like [1] or at least the official
reference manual [2].

Aside from C-style cast C++ supports four casts (in their safety
order, the safest first):
const_cast
static_cast
dynamic_cast
reinterpret_cast

One can see their preference order base on how explicit C-style
cast is being intrepreted by the C++ compiler [3].

So actually the reinterpret_cast should be avoided when it is
possible to use more strict casts, because reinterpret_cast
disables all safety checks aside from constness and volatileness
one.

[1] Stanley B. Lippman, Josee Lajoie, C++ Primer. Chapter 4.14
Types Conversion.
[2] https://en.cppreference.com
[3] https://en.cppreference.com/w/cpp/language/explicit_cast

Best regards,
Andrew Savchenko

[-- Attachment #2: Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-12 19:20           ` Andrey Savchenko
@ 2019-12-13  7:58             ` Aleksei Nikiforov
  0 siblings, 0 replies; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-13  7:58 UTC (permalink / raw)
  To: devel

12.12.2019 22:20, Andrey Savchenko пишет:
> On Mon, 9 Dec 2019 09:54:27 +0300 Aleksei Nikiforov wrote:
>> 07.12.2019 17:52, Andrey Savchenko пишет:
>>> Hi all!
>>>
>>> On Fri,  6 Dec 2019 18:36:55 +0300 Aleksei Nikiforov wrote:
>>>> This change should fix pointer arithmetic issues for e2k.
>>>
>>> This commit message is misleading. Pointer arithmetic is broken on
>>> all architectures, but by pure chance in happens to work correctly
>>> when gcc is used. On e2k the lcc compiler is used, so problem
>>> manifests itself. But this doesn't change the fact that pointer
>>> arithmetic was flawed on all architectures.
>>>
>>
>> Your first sentence contradicts later ones.
> 
> No.
> 
>> You just repeated my sentence about issue manifesting on e2k,
> 
> No.
> 
>> but you did it more verbosely.
> 
> Yes.
> 
>> Yes, there is a flaw for all architectures, but it manifests only for
>> e2k in practice, thus change fixes it for e2k. So, what's misleading there?
> 
> When a commit message is of concern it does matter what is written,
> and what was intended but kept behind the scenes is of no
> importance.
> 
> When one writes "issue A is fixed for B" this implies that A is
> B-specific issue, which is false in the discussed case.
> 

Is it a complain to latest patch version or old one? If it's to old one, 
I'll just skip it.

>>>> ---
>>>>    apt/apt-pkg/Makefile.am           |  1 +
>>>>    apt/apt-pkg/cacheiterators.h      | 26 ++++++++++++++------------
>>>>    apt/apt-pkg/contrib/mmap.cc       |  8 +++++---
>>>>    apt/apt-pkg/pkgcachegen.cc        | 29 +++++++++++++++--------------
>>>>    apt/apt-pkg/pkgcachegen.h         |  6 +++---
>>>>    apt/apt-pkg/rebase_pointer.h      | 16 ++++++++++++++++
>>>>    apt/apt-pkg/rpm/rpmlistparser.cc  |  5 +++--
>>>>    apt/apt-pkg/rpm/rpmpackagedata.cc |  2 +-
>>>>    8 files changed, 58 insertions(+), 35 deletions(-)
>>>>    create mode 100644 apt/apt-pkg/rebase_pointer.h
>>>>
>>>> diff --git a/apt/apt-pkg/Makefile.am b/apt/apt-pkg/Makefile.am
>>>> index 4c0d234..d038d01 100644
>>>> --- a/apt/apt-pkg/Makefile.am
>>>> +++ b/apt/apt-pkg/Makefile.am
>>>> @@ -94,6 +94,7 @@ libapt_pkg_la_SOURCES = \
>>>>    	pkgsystem.h \
>>>>    	policy.cc \
>>>>    	policy.h \
>>>> +	rebase_pointer.h \
>>>>    	repository.cc \
>>>>    	repository.h \
>>>>    	scopeexit.h \
>>>> diff --git a/apt/apt-pkg/cacheiterators.h b/apt/apt-pkg/cacheiterators.h
>>>> index a4bf670..118838e 100644
>>>> --- a/apt/apt-pkg/cacheiterators.h
>>>> +++ b/apt/apt-pkg/cacheiterators.h
>>>> @@ -34,6 +34,8 @@
>>>>    #pragma interface "apt-pkg/cacheiterators.h"
>>>>    #endif
>>>>    
>>>> +#include <apt-pkg/rebase_pointer.h>
>>>> +
>>>>    #include <set>
>>>>    
>>>>    // Package Iterator
>>>> @@ -85,11 +87,11 @@ class pkgCache::PkgIterator
>>>>       inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
>>>>       OkState State() const;
>>>>    
>>>> -   void ReMap(void const * const oldMap, void const * const newMap)
>>>> +   void ReMap(void *oldMap, void *newMap)
>>>>       {
>>>>          if (Owner == 0 || Pkg == 0)
>>>>             return;
>>>> -      Pkg += static_cast<Package const *>(newMap) - static_cast<Package const *>(oldMap);
>>>> +      Pkg = RebasePointer(Pkg, oldMap, newMap);
>>>>       }
>>>>    
>>>>       // Constructors
>>>> @@ -147,11 +149,11 @@ class pkgCache::VerIterator
>>>>       bool Automatic() const;
>>>>       VerFileIterator NewestFile() const;
>>>>    
>>>> -   void ReMap(void const * const oldMap, void const * const newMap)
>>>> +   void ReMap(void *oldMap, void *newMap)
>>>>       {
>>>>          if (Owner == 0 || Ver == 0)
>>>>             return;
>>>> -      Ver += static_cast<Version const *>(newMap) - static_cast<Version const *>(oldMap);
>>>> +      Ver = RebasePointer(Ver, oldMap, newMap);
>>>>       }
>>>>    
>>>>       inline VerIterator() : Ver(0), Owner(0) {};
>>>> @@ -220,11 +222,11 @@ class pkgCache::DepIterator
>>>>       inline const char *CompType() {return Owner->CompType(Dep->CompareOp);};
>>>>       inline const char *DepType() {return Owner->DepType(Dep->Type);};
>>>>    
>>>> -   void ReMap(void const * const oldMap, void const * const newMap)
>>>> +   void ReMap(void *oldMap, void *newMap)
>>>>       {
>>>>          if (Owner == 0 || Dep == 0)
>>>>             return;
>>>> -      Dep += static_cast<Dependency const *>(newMap) - static_cast<Dependency const *>(oldMap);
>>>> +      Dep = RebasePointer(Dep, oldMap, newMap);
>>>>       }
>>>>    
>>>>       inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) :
>>>> @@ -279,11 +281,11 @@ class pkgCache::PrvIterator
>>>>       inline PkgIterator OwnerPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[Prv->Version].ParentPkg);};
>>>>       inline unsigned long long Index() const {return Prv - Owner->ProvideP;};
>>>>    
>>>> -   void ReMap(void const * const oldMap, void const * const newMap)
>>>> +   void ReMap(void *oldMap, void *newMap)
>>>>       {
>>>>          if (Owner == 0 || Prv == 0)
>>>>             return;
>>>> -      Prv += static_cast<Provides const *>(newMap) - static_cast<Provides const *>(oldMap);
>>>> +      Prv = RebasePointer(Prv, oldMap, newMap);
>>>>       }
>>>>    
>>>>       inline PrvIterator() : Prv(0), Type(PrvVer), Owner(0)  {};
>>>> @@ -342,11 +344,11 @@ class pkgCache::PkgFileIterator
>>>>       bool IsOk();
>>>>       string RelStr();
>>>>    
>>>> -   void ReMap(void const * const oldMap, void const * const newMap)
>>>> +   void ReMap(void *oldMap, void *newMap)
>>>>       {
>>>>          if (Owner == 0 || File == 0)
>>>>             return;
>>>> -      File += static_cast<PackageFile const *>(newMap) - static_cast<PackageFile const *>(oldMap);
>>>> +      File = RebasePointer(File, oldMap, newMap);
>>>>       }
>>>>    
>>>>       // Constructors
>>>> @@ -383,11 +385,11 @@ class pkgCache::VerFileIterator
>>>>       inline PkgFileIterator File() const {return PkgFileIterator(*Owner,FileP->File + Owner->PkgFileP);};
>>>>       inline unsigned long long Index() const {return FileP - Owner->VerFileP;};
>>>>    
>>>> -   void ReMap(void const * const oldMap, void const * const newMap)
>>>> +   void ReMap(void *oldMap, void *newMap)
>>>>       {
>>>>          if (Owner == 0 || FileP == 0)
>>>>             return;
>>>> -      FileP += static_cast<VerFile const *>(newMap) - static_cast<VerFile const *>(oldMap);
>>>> +      FileP = RebasePointer(FileP, oldMap, newMap);
>>>>       }
>>>>    
>>>>       inline VerFileIterator() : Owner(0), FileP(0) {};
>>>> diff --git a/apt/apt-pkg/contrib/mmap.cc b/apt/apt-pkg/contrib/mmap.cc
>>>> index cf01be9..35f1a25 100644
>>>> --- a/apt/apt-pkg/contrib/mmap.cc
>>>> +++ b/apt/apt-pkg/contrib/mmap.cc
>>>> @@ -30,6 +30,7 @@
>>>>    #include <apt-pkg/configuration.h>
>>>>    #include <apt-pkg/mmap.h>
>>>>    #include <apt-pkg/error.h>
>>>> +#include <apt-pkg/rebase_pointer.h>
>>>>    
>>>>    #include <apti18n.h>
>>>>    
>>>> @@ -301,7 +302,7 @@ std::experimental::optional<map_ptrloc> DynamicMMap::Allocate(unsigned long Item
>>>>          Pool* oldPools = Pools;
>>>>          auto idxResult = RawAllocate(I->Count*ItemSize,ItemSize);
>>>>          if (Pools != oldPools)
>>>> -         I += Pools - oldPools;
>>>> +         I = RebasePointer(I, oldPools, Pools);
>>>>    
>>>>          // Does the allocation failed ?
>>>>          if (!idxResult)
>>>> @@ -371,7 +372,7 @@ bool DynamicMMap::Grow(unsigned long long size)
>>>>          Fd->Write(&C,sizeof(C));
>>>>       }
>>>>    
>>>> -   unsigned long const poolOffset = Pools - ((Pool*) Base);
>>>> +   void *old_base = Base;
>>>>    
>>>>       if (Fd != 0)
>>>>       {
>>>> @@ -408,7 +409,8 @@ bool DynamicMMap::Grow(unsigned long long size)
>>>>          memset((char*)Base + WorkSpace, 0, newSize - WorkSpace);
>>>>       }
>>>>    
>>>> -   Pools = (Pool*) Base + poolOffset;
>>>> +   if (Base != old_base)
>>>> +      Pools = RebasePointer(Pools, old_base, Base);
>>>>       WorkSpace = newSize;
>>>>    
>>>>       return true;
>>>> diff --git a/apt/apt-pkg/pkgcachegen.cc b/apt/apt-pkg/pkgcachegen.cc
>>>> index 654c81c..37364e9 100644
>>>> --- a/apt/apt-pkg/pkgcachegen.cc
>>>> +++ b/apt/apt-pkg/pkgcachegen.cc
>>>> @@ -26,6 +26,7 @@
>>>>    #include <apt-pkg/strutl.h>
>>>>    #include <apt-pkg/sptr.h>
>>>>    #include <apt-pkg/pkgsystem.h>
>>>> +#include <apt-pkg/rebase_pointer.h>
>>>>    
>>>>    #include <apti18n.h>
>>>>    
>>>> @@ -109,18 +110,18 @@ pkgCacheGenerator::~pkgCacheGenerator()
>>>>       Map.Sync(0,sizeof(pkgCache::Header));
>>>>    }
>>>>    									/*}}}*/
>>>> -void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newMap)
>>>> +void pkgCacheGenerator::ReMap(void *oldMap, void *newMap)
>>>>    {
>>>>       if (oldMap == newMap)
>>>>          return;
>>>>    
>>>>       Cache.ReMap(false);
>>>>    
>>>> -   CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap;
>>>> +   CurrentFile = RebasePointer(CurrentFile, oldMap, newMap);
>>>>    
>>>>       for (size_t i = 0; i < _count(UniqHash); ++i)
>>>>          if (UniqHash[i] != 0)
>>>> -         UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap;
>>>> +         UniqHash[i] = RebasePointer(UniqHash[i], oldMap, newMap);
>>>>    
>>>>       for (auto i = Dynamic<pkgCache::PkgIterator>::toReMap.begin();
>>>>            i != Dynamic<pkgCache::PkgIterator>::toReMap.end(); ++i)
>>>> @@ -147,7 +148,7 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM
>>>>    // CacheGenerator::WriteStringInMap					/*{{{*/
>>>>    std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(const char *String,
>>>>    					unsigned long Len) {
>>>> -   void const * const oldMap = Map.Data();
>>>> +   void *oldMap = Map.Data();
>>>>       const auto index = Map.WriteString(String, Len);
>>>>       if (index)
>>>>          ReMap(oldMap, Map.Data());
>>>> @@ -156,7 +157,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(cons
>>>>    									/*}}}*/
>>>>    // CacheGenerator::WriteStringInMap					/*{{{*/
>>>>    std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(const char *String) {
>>>> -   void const * const oldMap = Map.Data();
>>>> +   void *oldMap = Map.Data();
>>>>       const auto index = Map.WriteString(String);
>>>>       if (index)
>>>>          ReMap(oldMap, Map.Data());
>>>> @@ -164,7 +165,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteStringInMap(cons
>>>>    }
>>>>    									/*}}}*/
>>>>    std::experimental::optional<map_ptrloc> pkgCacheGenerator::AllocateInMap(unsigned long size) {/*{{{*/
>>>> -   void const * const oldMap = Map.Data();
>>>> +   void *oldMap = Map.Data();
>>>>       const auto index = Map.Allocate(size);
>>>>       if (index)
>>>>          ReMap(oldMap, Map.Data());
>>>> @@ -229,7 +230,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>>>>          pkgCache::VerIterator Ver = Pkg.VersionList();
>>>>          Dynamic<pkgCache::VerIterator> DynVer(Ver);
>>>>          map_ptrloc *Last = &Pkg->VersionList;
>>>> -      const void * oldMap = Map.Data();
>>>> +      void *oldMap = Map.Data();
>>>>          int Res = 1;
>>>>          for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
>>>>          {
>>>> @@ -271,7 +272,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>>>>    
>>>>          if (oldMap != Map.Data())
>>>>          {
>>>> -         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
>>>> +         Last = RebasePointer(Last, oldMap, Map.Data());
>>>>             oldMap = Map.Data();
>>>>          }
>>>>    
>>>> @@ -297,7 +298,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
>>>>                                  PackageName.c_str(), 1);
>>>>    
>>>>          if (oldMap != Map.Data())
>>>> -         Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
>>>> +         Last = RebasePointer(Last, oldMap, Map.Data());
>>>>          *Last = *verindex;
>>>>    
>>>>          Ver->ParentPkg = Pkg.Index();
>>>> @@ -553,7 +554,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
>>>>    					       unsigned int Op,
>>>>    					       unsigned int Type)
>>>>    {
>>>> -   void const * const oldMap = Owner->Map.Data();
>>>> +   void *oldMap = Owner->Map.Data();
>>>>       pkgCache &Cache = Owner->Cache;
>>>>       
>>>>       // Get a structure
>>>> @@ -605,7 +606,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
>>>>    	 OldDepLast = &D->NextDepends;
>>>>          OldDepVer = Ver;
>>>>       } else if (oldMap != Owner->Map.Data())
>>>> -      OldDepLast += (map_ptrloc*) Owner->Map.Data() - (map_ptrloc*) oldMap;
>>>> +      OldDepLast = RebasePointer(OldDepLast, oldMap, Owner->Map.Data());
>>>>    
>>>>       // Is it a file dependency?
>>>>       if (PackageName[0] == '/')
>>>> @@ -739,7 +740,7 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
>>>>       }
>>>>       
>>>>       // Get a structure
>>>> -   void const * const oldMap = Map.Data();
>>>> +   void *oldMap = Map.Data();
>>>>       const auto Item = AllocateInMap(sizeof(pkgCache::StringItem));
>>>>       const auto idxString = WriteStringInMap(S, Size);
>>>>       if ((!Item) || (!idxString))
>>>> @@ -747,8 +748,8 @@ std::experimental::optional<map_ptrloc> pkgCacheGenerator::WriteUniqString(const
>>>>    
>>>>       if (oldMap != Map.Data())
>>>>       {
>>>> -      Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
>>>> -      I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap;
>>>> +      Last = RebasePointer(Last, oldMap, Map.Data());
>>>> +      I = RebasePointer(I, oldMap, Map.Data());
>>>>       }
>>>>    
>>>>       *Last = *Item;
>>>> diff --git a/apt/apt-pkg/pkgcachegen.h b/apt/apt-pkg/pkgcachegen.h
>>>> index 77075a6..0faf6e1 100644
>>>> --- a/apt/apt-pkg/pkgcachegen.h
>>>> +++ b/apt/apt-pkg/pkgcachegen.h
>>>> @@ -72,7 +72,7 @@ class pkgCacheGenerator
>>>>       class DynamicFunction
>>>>       {
>>>>       public:
>>>> -      typedef std::function<void(const void *, const void *)> function;
>>>> +      typedef std::function<void(void *, void *)> function;
>>>>    
>>>>          static std::set<DynamicFunction*> toReMap;
>>>>    
>>>> @@ -93,7 +93,7 @@ class pkgCacheGenerator
>>>>             toReMap.erase(this);
>>>>          }
>>>>    
>>>> -      void call(const void *oldMap, const void *newMap)
>>>> +      void call(void *oldMap, void *newMap)
>>>>          {
>>>>             if (m_function)
>>>>                m_function(oldMap, newMap);
>>>> @@ -140,7 +140,7 @@ class pkgCacheGenerator
>>>>       // CNC:2003-03-18
>>>>       inline void ResetFileDeps() {FoundFileDeps = false;};
>>>>    
>>>> -   void ReMap(void const * const oldMap, void const * const newMap);
>>>> +   void ReMap(void *oldMap, void *newMap);
>>>>    
>>>>       pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress);
>>>>       ~pkgCacheGenerator();
>>>> diff --git a/apt/apt-pkg/rebase_pointer.h b/apt/apt-pkg/rebase_pointer.h
>>>> new file mode 100644
>>>> index 0000000..f6b3c15
>>>> --- /dev/null
>>>> +++ b/apt/apt-pkg/rebase_pointer.h
>>>> @@ -0,0 +1,16 @@
>>>> +#ifndef PKGLIB_REBASE_POINTER_H
>>>> +#define PKGLIB_REBASE_POINTER_H
>>>> +
>>>> +template <typename T>
>>>> +static inline T* RebasePointer(T *ptr, void *old_base, void *new_base)
>>>> +{
>>>> +   return reinterpret_cast<T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(old_base)));
>>>> +}
>>>> +
>>>> +template <typename T>
>>>> +static inline const T* RebasePointer(const T *ptr, void *old_base, void *new_base)
>>>> +{
>>>> +   return reinterpret_cast<const T*>(reinterpret_cast<char*>(new_base) + (reinterpret_cast<const char*>(ptr) - reinterpret_cast<char*>(old_base)));
>>>> +}
>>>> +
>>>> +#endif
>>>> diff --git a/apt/apt-pkg/rpm/rpmlistparser.cc b/apt/apt-pkg/rpm/rpmlistparser.cc
>>>> index 9b2e9ad..bd13b99 100644
>>>> --- a/apt/apt-pkg/rpm/rpmlistparser.cc
>>>> +++ b/apt/apt-pkg/rpm/rpmlistparser.cc
>>>> @@ -25,6 +25,7 @@
>>>>    #include <apt-pkg/strutl.h>
>>>>    #include <apt-pkg/crc-16.h>
>>>>    #include <apt-pkg/tagfile.h>
>>>> +#include <apt-pkg/rebase_pointer.h>
>>>>    
>>>>    #include <apti18n.h>
>>>>    
>>>> @@ -50,13 +51,13 @@ rpmListParser::rpmListParser(RPMHandler *Handler)
>>>>       {
>>>>          SeenPackages.reset(new SeenPackagesType);
>>>>          m_SeenPackagesRealloc.reset(new pkgCacheGenerator::DynamicFunction(
>>>> -         [this] (void const *oldMap, void const *newMap)
>>>> +         [this] (void *oldMap, void *newMap)
>>>>          {
>>>>             SeenPackagesType tmp;
>>>>    
>>>>             for (auto iter: *SeenPackages)
>>>>             {
>>>> -            tmp.insert(iter + (static_cast<const char *>(newMap) - static_cast<const char *>(oldMap)));
>>>> +            tmp.insert(RebasePointer(iter, oldMap, newMap));
>>>>             }
>>>>    
>>>>             SeenPackages->swap(tmp);
>>>> diff --git a/apt/apt-pkg/rpm/rpmpackagedata.cc b/apt/apt-pkg/rpm/rpmpackagedata.cc
>>>> index 61c15d5..d6c677b 100644
>>>> --- a/apt/apt-pkg/rpm/rpmpackagedata.cc
>>>> +++ b/apt/apt-pkg/rpm/rpmpackagedata.cc
>>>> @@ -23,7 +23,7 @@ RPMPackageData::RPMPackageData()
>>>>    #endif
>>>>    {
>>>>       m_VerMapRealloc.reset(new pkgCacheGenerator::DynamicFunction(
>>>> -      [this] (void const *oldMap, void const *newMap)
>>>> +      [this] (void *oldMap, void *newMap)
>>>>       {
>>>>          for (auto iter1 = VerMap.begin(); iter1 != VerMap.end(); ++iter1)
>>>>          {
>>>
>>>
>>> Best regards,
>>> Andrew Savchenko
>>>
>>>
>>> _______________________________________________
>>> Devel mailing list
>>> Devel@lists.altlinux.org
>>> https://lists.altlinux.org/mailman/listinfo/devel
>>>
>> _______________________________________________
>> Devel mailing list
>> Devel@lists.altlinux.org
>> https://lists.altlinux.org/mailman/listinfo/devel
> 
> Best regards,
> Andrew Savchenko
> 
> 
> _______________________________________________
> Devel mailing list
> Devel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel
> 


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [devel] [PATCH for apt 2/2 v2] Fix pointer arithmetics
  2019-12-12 19:43                       ` Andrey Savchenko
@ 2019-12-13  8:01                         ` Aleksei Nikiforov
  0 siblings, 0 replies; 34+ messages in thread
From: Aleksei Nikiforov @ 2019-12-13  8:01 UTC (permalink / raw)
  To: devel

12.12.2019 22:43, Andrey Savchenko пишет:
> On Wed, 11 Dec 2019 10:50:22 +0300 Aleksei Nikiforov wrote:
>> 11.12.2019 1:20, Dmitry V. Levin пишет:
>>> On Tue, Dec 10, 2019 at 01:58:17PM +0300, Aleksei Nikiforov wrote:
>>>> 10.12.2019 13:20, Dmitry V. Levin пишет:
>>>>> On Tue, Dec 10, 2019 at 11:18:06AM +0300, Aleksei Nikiforov wrote:
>>>>>> 10.12.2019 3:07, Dmitry V. Levin пишет:
>>>>>>> On Mon, Dec 09, 2019 at 10:08:42AM +0300, Aleksei Nikiforov wrote:
>>>>>>>> 09.12.2019 2:21, Dmitry V. Levin пишет:
>>>>>>>>> On Fri, Dec 06, 2019 at 06:36:55PM +0300, Aleksei Nikiforov wrote:
>>>>>>>>> [...]
>>>>>>>>>> @@ -85,11 +87,11 @@ class pkgCache::PkgIterator
>>>>>>>>>>          inline unsigned long long Index() const {return Pkg - Owner->PkgP;};
>>>>>>>>>>          OkState State() const;
>>>>>>>>>>       
>>>>>>>>>> -   void ReMap(void const * const oldMap, void const * const newMap)
>>>>>>>>>> +   void ReMap(void *oldMap, void *newMap)
>>>>>>>>>
>>>>>>>>> Is there any particular reason for stripping const here and in other
>>>>>>>>> similar places?
>>>>>>>>
>>>>>>>> Yes, it's needed due to issues emerging from mixing const and non-const
>>>>>>>> pointers with new and allegedly more proper way of calculating rebased
>>>>>>>> pointers.
>>>>>>>
>>>>>>> Sorry, I don't find this argument convincing.
>>>>>>> I have experienced no const issues in my version of this fix.
>>>>>>
>>>>>> Your version is using C-style casts in C++ code. Of course, I could use
>>>>>> C-style casts or const_cast-s too to work around const correctness
>>>>>> issues (i.e. to just hide these issues), and it'd work like your
>>>>>> version. But I'd like to remind you that APT is C++ project, not a C
>>>>>> project. What might be ok for C is sometimes a dirty ugly hack in modern
>>>>>> C++.
>>>>>
>>>>> Sorry, I don't share you point of view on this matter.
>>>>> Being a C++ project allows you to use C++ constructs, that's true,
>>>>> but why do you think it prevents you from using C constructs when
>>>>> appropriate?
>>>>
>>>> I didn't say that something prevents from using C constructs when
>>>> appropriate. I'm saying that these constructs are not appropriate here.
>>>
>>> Why do you think they are not appropriate here?
>>>
>>
>> In good C++ code there is no place for const_cast.
> 
> This statement is ungrounded.
> 

It is grounded. Read my answer below (and links [2] and [3] to 
documentation you provided).

>> Maybe there are some
>> exceptions to it, but they have to be justified. It doesn't matter that
>> you are hiding it behind C-style cast.
> 
> Please read some good book on C++ like [1] or at least the official
> reference manual [2].

Same to you.

> 
> Aside from C-style cast C++ supports four casts (in their safety
> order, the safest first):
> const_cast
> static_cast
> dynamic_cast
> reinterpret_cast
> 

Now, this statement is ungrounded. Where did you get this list from? Do 
you serously think that dynamic_cast is less safe than static_cast? And 
how did you judge safety of const_cast vs safety of reinterpret_cast? 
How did you get const_cast more safe than static_cast and dynamic_cast?

For your education: const_cast is indeed safe when 'T' is casted to 
'const T', but when 'const T' is casted to 'T' it can lead to UB, 
assuming 'T' is a non-const type.

Read your own documentation:

https://en.cppreference.com/w/cpp/language/const_cast

> One can see their preference order base on how explicit C-style
> cast is being intrepreted by the C++ compiler [3].
> 
> So actually the reinterpret_cast should be avoided when it is
> possible to use more strict casts, because reinterpret_cast
> disables all safety checks aside from constness and volatileness
> one.
> 

Please show me how you'd write this code without reinterpret_cast and 
without C-style cast since it will just implicitly use reinterpret_cast. 
C-style cast is the least strict cast in C++ since it tries to apply 
every cast except for dynamic_cast. I agree with you that stricter casts 
should be applied, and thus there's no place for C-style casts.

> [1] Stanley B. Lippman, Josee Lajoie, C++ Primer. Chapter 4.14
> Types Conversion.
> [2] https://en.cppreference.com
> [3] https://en.cppreference.com/w/cpp/language/explicit_cast
> 
> Best regards,
> Andrew Savchenko
> 
> 
> _______________________________________________
> Devel mailing list
> Devel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel
> 


^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2019-12-13  8:01 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-06 13:16 [devel] [PATCH for apt 1/2] Add option for debugging DynamicMMap::Allocate Aleksei Nikiforov
2019-12-06 13:16 ` [devel] [PATCH for apt 2/2] Fix pointer arithmetics Aleksei Nikiforov
2019-12-06 13:36   ` Ivan A. Melnikov
2019-12-06 15:32     ` Aleksei Nikiforov
2019-12-06 15:36     ` [devel] [PATCH for apt 2/2 v2] " Aleksei Nikiforov
2019-12-07 14:52       ` Andrey Savchenko
2019-12-08 22:56         ` Dmitry V. Levin
2019-12-09  6:54         ` Aleksei Nikiforov
2019-12-12 19:20           ` Andrey Savchenko
2019-12-13  7:58             ` Aleksei Nikiforov
2019-12-08 23:21       ` Dmitry V. Levin
2019-12-09  7:08         ` Aleksei Nikiforov
2019-12-10  0:07           ` Dmitry V. Levin
2019-12-10  8:18             ` Aleksei Nikiforov
2019-12-10 10:20               ` Dmitry V. Levin
2019-12-10 10:58                 ` Aleksei Nikiforov
2019-12-10 22:20                   ` Dmitry V. Levin
2019-12-11  7:50                     ` Aleksei Nikiforov
2019-12-12 19:43                       ` Andrey Savchenko
2019-12-13  8:01                         ` Aleksei Nikiforov
2019-12-08 23:31   ` [devel] [PATCH for apt 2/2] " Dmitry V. Levin
2019-12-09  7:09     ` Aleksei Nikiforov
2019-12-09  7:16     ` [devel] [PATCH for apt 2/2 v3] " Aleksei Nikiforov
2019-12-09 23:54   ` [devel] [PATCH apt 0/3] Fix 0.5.15lorg2-alt70~9 fallout Dmitry V. Levin
2019-12-09 23:56     ` [devel] [PATCH apt 1/3] apt-pkg/cacheiterators.h: revert #include <set> Dmitry V. Levin
2019-12-09 23:56     ` [devel] [PATCH apt 2/3] apt-pkg/contrib/mmap.cc: revert confusing change of Flags to this->Flags Dmitry V. Levin
2019-12-09 23:56     ` [devel] [PATCH apt 3/3] Fix UB in pointer arithmetic Dmitry V. Levin
2019-12-10  8:18       ` Aleksei Nikiforov
2019-12-08 22:50 ` [devel] [PATCH for apt 1/2] Add option for debugging DynamicMMap::Allocate Dmitry V. Levin
2019-12-09  6:58   ` Aleksei Nikiforov
2019-12-09 10:24     ` Dmitry V. Levin
2019-12-09 11:03       ` [devel] [PATCH for apt 1/2 v3] Add Debug::DynamicMMap::Allocate option Aleksei Nikiforov
2019-12-09 22:59         ` Dmitry V. Levin
2019-12-09  7:00   ` [devel] [PATCH for apt 1/2 v2] Add option for debugging Debug::DynamicMMap::Allocate Aleksei Nikiforov

ALT Linux Team development discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/devel/0 devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 devel devel/ http://lore.altlinux.org/devel \
		devel@altlinux.org devel@altlinux.ru devel@lists.altlinux.org devel@lists.altlinux.ru devel@linux.iplabs.ru mandrake-russian@linuxteam.iplabs.ru sisyphus@linuxteam.iplabs.ru
	public-inbox-index devel

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git