esx: generator: fix free of elements in lists

When a list is freed, we iterate through all the items, invoking the
free function for each; the actual free function called for each element
is the function of the actual type of each element, and thus the @_next
pointer in the element struct has the same type as the element itself.
Currently, the free function gets the parent of the current element
type, and invoke its free function to continue freeing the list.
However, in case the hierarchy of the classes has more than 1 level
(i.e. Class <- SubClass <- SubSubClass), the invoked free function is
only the parent class' one, and not the actual base class of the
hierarchy.

To fix that, change the generator to get the base class of a class, and
invoking that instead.  Also, avoid to set the @_next back, as it is not
needed.

Fixes commits 5cff36e39a and
f76c6dde2e.

Signed-off-by: Pino Toscano <ptoscano@redhat.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
This commit is contained in:
Pino Toscano 2020-09-10 15:08:24 +02:00
parent 3c79c08299
commit 8508799f2d

View File

@ -751,13 +751,13 @@ class Object(GenericObject):
source += "{\n"
if self.features & Object.FEATURE__LIST:
if self.extends is not None:
base_class = get_base_class(self)
if base_class:
# avoid "dereferencing type-punned pointer will break
# strict-aliasing rules" warnings
source += " esxVI_%s *next = (esxVI_%s *)item->_next;\n\n" \
% (self.extends, self.extends)
source += " esxVI_%s_Free(&next);\n" % self.extends
source += " item->_next = (esxVI_%s *)next;\n\n" % self.name
source += " esxVI_%s *baseNext = (esxVI_%s *)item->_next;\n" \
% (base_class, base_class)
source += " esxVI_%s_Free(&baseNext);\n\n" % base_class
else:
source += " esxVI_%s_Free(&item->_next);\n\n" % self.name
@ -1250,6 +1250,21 @@ def is_known_type(type):
type in enums_by_name)
def get_base_class(obj):
if not obj.extends:
return None
base_class = None
try:
base_class = base_class_by_name[obj.extends]
except KeyError:
parent = objects_by_name[obj.extends]
base_class = get_base_class(parent)
if not base_class:
base_class = parent.name
base_class_by_name[name] = base_class
return base_class
def open_file(filename):
return open(filename, "wt")
@ -1341,6 +1356,7 @@ managed_objects_by_name = {}
enums_by_name = {}
methods_by_name = {}
block = None
base_class_by_name = {}
# parse input file