diff options
author | Jens Georg <mail@jensge.org> | 2022-01-02 20:06:26 +0100 |
---|---|---|
committer | Jens Georg <mail@jensge.org> | 2022-01-02 20:39:53 +0100 |
commit | b441cb813c751821f1a379d343274b7b90b71da3 (patch) | |
tree | cc918a0ef2b844bcbc7b742f7cad8bd5a4ca2807 | |
parent | 0cb305b4ae1e7f999392aa69d549bce4827eb1a3 (diff) | |
download | gupnp-b441cb813c751821f1a379d343274b7b90b71da3.tar.gz |
Device,Service,RootDevice: Fix use after free
Devices and Services created by a RootDevice were keeping a pointer to
their XML element, but not to the document, so it could happen that if
the service lived longer than the RootDevice, the element pointer was
invalid.
This is already implemented like this for DeviceProxy and ServiceProxy.
No idea why the description-doc property was introduced additionally
to the "document" property on DeviceInfo.
Fixes #42
-rw-r--r-- | libgupnp/gupnp-device-info.c | 25 | ||||
-rw-r--r-- | libgupnp/gupnp-resource-factory.c | 48 | ||||
-rw-r--r-- | libgupnp/gupnp-root-device.c | 76 |
3 files changed, 80 insertions, 69 deletions
diff --git a/libgupnp/gupnp-device-info.c b/libgupnp/gupnp-device-info.c index c7d9374..9d514ce 100644 --- a/libgupnp/gupnp-device-info.c +++ b/libgupnp/gupnp-device-info.c @@ -309,19 +309,18 @@ gupnp_device_info_class_init (GUPnPDeviceInfoClass *klass) * * Stability: Private **/ - g_object_class_install_property - (object_class, - PROP_DOCUMENT, - g_param_spec_object ("document", - "Document", - "The XML document related to this " - "device", - GUPNP_TYPE_XML_DOC, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB)); + g_object_class_install_property ( + object_class, + PROP_DOCUMENT, + g_param_spec_object ("document", + "Document", + "The XML document related to this " + "device", + GUPNP_TYPE_XML_DOC, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); /** * GUPnPDeviceInfo:element: diff --git a/libgupnp/gupnp-resource-factory.c b/libgupnp/gupnp-resource-factory.c index 6d2b798..9e441dc 100644 --- a/libgupnp/gupnp-resource-factory.c +++ b/libgupnp/gupnp-resource-factory.c @@ -25,6 +25,7 @@ #include <config.h> #include <string.h> +#include "gupnp-device-info-private.h" #include "gupnp-resource-factory-private.h" #include "gupnp-root-device.h" @@ -334,14 +335,25 @@ gupnp_resource_factory_create_device (GUPnPResourceFactory *factory, element, GUPNP_TYPE_DEVICE); + GUPnPXMLDoc *doc = _gupnp_device_info_get_document ( + GUPNP_DEVICE_INFO (root_device)); device = g_object_new (device_type, - "resource-factory", factory, - "context", context, - "root-device", root_device, - "location", location, - "udn", udn, - "url-base", url_base, - "element", element, + "resource-factory", + factory, + "context", + context, + "root-device", + root_device, + "location", + location, + "udn", + udn, + "url-base", + url_base, + "document", + doc, + "element", + element, NULL); return device; @@ -390,13 +402,23 @@ gupnp_resource_factory_create_service (GUPnPResourceFactory *factory, element, GUPNP_TYPE_SERVICE); + GUPnPXMLDoc *doc = _gupnp_device_info_get_document ( + GUPNP_DEVICE_INFO (root_device)); service = g_object_new (service_type, - "context", context, - "root-device", root_device, - "location", location, - "udn", udn, - "url-base", url_base, - "element", element, + "context", + context, + "root-device", + root_device, + "location", + location, + "udn", + udn, + "url-base", + url_base, + "document", + doc, + "element", + element, NULL); return service; diff --git a/libgupnp/gupnp-root-device.c b/libgupnp/gupnp-root-device.c index 3c337fc..73734a3 100644 --- a/libgupnp/gupnp-root-device.c +++ b/libgupnp/gupnp-root-device.c @@ -19,9 +19,10 @@ #include <libgssdp/gssdp-resource-group.h> -#include "gupnp-root-device.h" #include "gupnp-context-private.h" +#include "gupnp-device-info-private.h" #include "gupnp-error.h" +#include "gupnp-root-device.h" #include "http-headers.h" #include "xml-util.h" @@ -35,8 +36,6 @@ gupnp_root_device_initable_init (GInitable *initable, GError **error); struct _GUPnPRootDevicePrivate { - GUPnPXMLDoc *description_doc; - GSSDPResourceGroup *group; char *description_path; @@ -56,7 +55,6 @@ G_DEFINE_TYPE_EXTENDED (GUPnPRootDevice, enum { PROP_0, - PROP_DESCRIPTION_DOC, PROP_DESCRIPTION_PATH, PROP_DESCRIPTION_DIR, PROP_AVAILABLE @@ -72,7 +70,6 @@ gupnp_root_device_finalize (GObject *object) device = GUPNP_ROOT_DEVICE (object); priv = gupnp_root_device_get_instance_private (device); - g_clear_object (&priv->description_doc); g_free (priv->description_path); g_free (priv->description_dir); g_free (priv->relative_location); @@ -125,9 +122,6 @@ gupnp_root_device_set_property (GObject *object, priv = gupnp_root_device_get_instance_private (device); switch (property_id) { - case PROP_DESCRIPTION_DOC: - priv->description_doc = g_value_dup_object (value); - break; case PROP_DESCRIPTION_PATH: priv->description_path = g_value_dup_string (value); break; @@ -342,11 +336,13 @@ gupnp_root_device_initable_init (GInitable *initable, priv->description_path, NULL); + GUPnPXMLDoc *description_doc = + _gupnp_device_info_get_document (GUPNP_DEVICE_INFO (device)); /* Check whether we have a parsed description document */ - if (priv->description_doc == NULL) { + if (description_doc == NULL) { /* We don't, so load and parse it */ - priv->description_doc = load_and_parse (desc_path); - if (priv->description_doc == NULL) { + description_doc = load_and_parse (desc_path); + if (description_doc == NULL) { g_set_error_literal (error, GUPNP_XML_ERROR, GUPNP_XML_ERROR_PARSE, @@ -354,13 +350,15 @@ gupnp_root_device_initable_init (GInitable *initable, goto DONE; } + } else { + g_object_ref (description_doc); } /* Find correct element */ - root_element = xml_util_get_element ((xmlNode *) - gupnp_xml_doc_get_doc (priv->description_doc), - "root", - NULL); + root_element = xml_util_get_element ( + (xmlNode *) gupnp_xml_doc_get_doc (description_doc), + "root", + NULL); if (!root_element) { g_set_error_literal (error, GUPNP_XML_ERROR, @@ -418,8 +416,12 @@ gupnp_root_device_initable_init (GInitable *initable, /* Set additional properties */ g_object_set (G_OBJECT (device), - "location", location, - "url-base", url_base, + "location", + location, + "url-base", + url_base, + "document", + description_doc, NULL); g_uri_unref (url_base); @@ -443,6 +445,8 @@ gupnp_root_device_initable_init (GInitable *initable, if (uri) g_uri_unref (uri); + g_clear_object (&description_doc); + g_free (desc_path); g_free (location); @@ -462,26 +466,6 @@ gupnp_root_device_class_init (GUPnPRootDeviceClass *klass) object_class->finalize = gupnp_root_device_finalize; /** - * GUPnPRootDevice:description-doc: - * - * Device description document. Constructor property. - * - * Since: 0.14.0 - **/ - g_object_class_install_property - (object_class, - PROP_DESCRIPTION_DOC, - g_param_spec_object ("description-doc", - "Description document", - "Device description document", - GUPNP_TYPE_XML_DOC, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB)); - - /** * GUPnPRootDevice:description-path: * * The path to device description document. This could either be an @@ -602,12 +586,18 @@ gupnp_root_device_new_full (GUPnPContext *context, return g_initable_new (GUPNP_TYPE_ROOT_DEVICE, NULL, error, - "context", context, - "resource-factory", factory, - "root-device", NULL, - "description-doc", description_doc, - "description-path", description_path, - "description-dir", description_dir, + "context", + context, + "resource-factory", + factory, + "root-device", + NULL, + "document", + description_doc, + "description-path", + description_path, + "description-dir", + description_dir, NULL); } |