mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-23 13:05:27 +00:00
util: Add magic number check for object validity
The virObjectIsClass API has only ever checked object validity based on if the @obj is not NULL and it was derived from some class. While this has worked well in general, there is one additional check that could be made prior to calling virClassIsDerivedFrom which loops through the classes checking the magic number against the klass expected magic number. If by chance a non virObject is passed, rather than assuming the void * @obj is a _virObject and thus offsetting to obj->klass, obj->magic, and obj->parent, let's check that the void * @obj has at least the "base part" of the magic number in the right place and generate a more specific VIR_WARN message if not. There are many consumers to virObjectIsClass, include the locking primitives virObject{Lock|Unlock}, virObjectRWLock{Read|Write}, and virObjectRWUnlock. For those callers, the locking call will not fail, but it also will not attempt a virMutex* call which will "most likely" fail since the &obj->lock is used. In order to avoid some possible future wrap on the 0xCAFExxxx value, add a check during initialization that some new class won't cause the wrap. Should be good for a few years at least! It is still left up to the caller to handle the failed API calls just as it would be if it passed a NULL opaque pointer anyobj.
This commit is contained in:
parent
19f4395230
commit
dfa0efbb77
@ -47,14 +47,21 @@ struct _virClass {
|
||||
virObjectDisposeCallback dispose;
|
||||
};
|
||||
|
||||
#define VIR_OBJECT_NOTVALID(obj) (!obj || ((obj->u.s.magic & 0xFFFF0000) != 0xCAFE0000))
|
||||
|
||||
#define VIR_OBJECT_USAGE_PRINT_WARNING(anyobj, objclass) \
|
||||
do { \
|
||||
virObjectPtr obj = anyobj; \
|
||||
if (!obj) \
|
||||
VIR_WARN("Object cannot be NULL"); \
|
||||
else \
|
||||
if (VIR_OBJECT_NOTVALID(obj)) { \
|
||||
if (!obj) \
|
||||
VIR_WARN("Object cannot be NULL"); \
|
||||
else \
|
||||
VIR_WARN("Object %p has a bad magic number %X", \
|
||||
obj, obj->u.s.magic); \
|
||||
} else { \
|
||||
VIR_WARN("Object %p (%s) is not a %s instance", \
|
||||
anyobj, obj->klass->name, #objclass); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
@ -177,9 +184,14 @@ virClassNew(virClassPtr parent,
|
||||
goto error;
|
||||
|
||||
klass->parent = parent;
|
||||
klass->magic = virAtomicIntInc(&magicCounter);
|
||||
if (klass->magic > 0xCAFEFFFF) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("too many object classes defined"));
|
||||
goto error;
|
||||
}
|
||||
if (VIR_STRDUP(klass->name, name) < 0)
|
||||
goto error;
|
||||
klass->magic = virAtomicIntInc(&magicCounter);
|
||||
klass->objectSize = objectSize;
|
||||
klass->dispose = dispose;
|
||||
|
||||
@ -535,7 +547,7 @@ virObjectIsClass(void *anyobj,
|
||||
virClassPtr klass)
|
||||
{
|
||||
virObjectPtr obj = anyobj;
|
||||
if (!obj)
|
||||
if (VIR_OBJECT_NOTVALID(obj))
|
||||
return false;
|
||||
|
||||
return virClassIsDerivedFrom(obj->klass, klass);
|
||||
|
Loading…
x
Reference in New Issue
Block a user