From b2c827e516c82a1efe58602e10f114c104dd7476 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Thu, 15 Oct 2015 01:12:02 +0200 Subject: Detect trivial loops Fixed bugs: - https://launchpad.net/bugs/1328079 (bzr r14412) --- src/uri-references.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/uri-references.cpp') diff --git a/src/uri-references.cpp b/src/uri-references.cpp index 04f904d39..0aae9b39d 100644 --- a/src/uri-references.cpp +++ b/src/uri-references.cpp @@ -75,6 +75,7 @@ bool URIReference::_acceptObject(SPObject *obj) const { for(int i=positions.size()-2;i>=0;i--)owner=owner->childList(false)[positions[i]]; } //once we have the "original" object (hopefully) we look at who is referencing it + if(obj == owner)return false; std::list todo(owner->hrefList); todo.push_front(owner->parent); while(!todo.empty()){ -- cgit v1.2.3 From b39fc82af6e1320d3c2b301a1639965b04f05fd9 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Thu, 15 Oct 2015 01:13:10 +0200 Subject: clang-format (bzr r14413) --- src/uri-references.cpp | 159 +++++++++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 72 deletions(-) (limited to 'src/uri-references.cpp') diff --git a/src/uri-references.cpp b/src/uri-references.cpp index 0aae9b39d..b6ccdbf5f 100644 --- a/src/uri-references.cpp +++ b/src/uri-references.cpp @@ -26,74 +26,91 @@ namespace Inkscape { URIReference::URIReference(SPObject *owner) - : _owner(owner), _owner_document(NULL), _obj(NULL), _uri(NULL) + : _owner(owner) + , _owner_document(NULL) + , _obj(NULL) + , _uri(NULL) { g_assert(_owner != NULL); /* FIXME !!! attach to owner's destroy signal to clean up in case */ } URIReference::URIReference(SPDocument *owner_document) - : _owner(NULL), _owner_document(owner_document), _obj(NULL), _uri(NULL) + : _owner(NULL) + , _owner_document(owner_document) + , _obj(NULL) + , _uri(NULL) { g_assert(_owner_document != NULL); } -URIReference::~URIReference() -{ - detach(); -} +URIReference::~URIReference() { detach(); } /* * The main ideas here are: * (1) "If we are inside a clone, then we can accept if and only if our "original thing" can accept the reference" - * (this caused problems when there are clones because a change in ids triggers signals for the object hrefing this id, but also its cloned reprs - * (descendants of referencing an ancestor of the href'ing object)). The way it is done here is *atrocious*, but i could not find a better way. + * (this caused problems when there are clones because a change in ids triggers signals for the object hrefing this id, + *but also its cloned reprs + * (descendants of referencing an ancestor of the href'ing object)). The way it is done here is *atrocious*, but i + *could not find a better way. * FIXME: find a better and safer way to find the "original object" of anyone with the flag ->cloned * - * (2) Once we have an (potential owner) object, it can accept a href to obj, iff the graph of objects where directed edges are + * (2) Once we have an (potential owner) object, it can accept a href to obj, iff the graph of objects where directed + *edges are * either parent->child relations , *** or href'ing to href'ed *** relations, stays acyclic. - * We can go either from owner and up in the tree, or from obj and down, in either case this will be in the worst case linear in the number of objects. - * There are no easy objects allowing to do the second proposition, while "hrefList" is a "list of objects href'ing us", so we'll take this. + * We can go either from owner and up in the tree, or from obj and down, in either case this will be in the worst case + *linear in the number of objects. + * There are no easy objects allowing to do the second proposition, while "hrefList" is a "list of objects href'ing us", + *so we'll take this. * Then we keep a set of already visited elements, and do a DFS on this graph. if we find obj, then BOOM. */ -bool URIReference::_acceptObject(SPObject *obj) const { - //we go back following hrefList and parent to find if the object already references ourselves indirectly - std::set done; - SPObject * owner = getOwner(); - if(!owner)return true; - while(owner->cloned){ - std::vector positions; - while(owner->cloned){ - int position=0; - SPObject* c = owner->parent->firstChild(); - while(c != owner && dynamic_cast(c) ){position++;c=c->next;} - positions.push_back(position); - owner=owner->parent; - } - owner = ((SPUse*)owner)->get_original(); - for(int i=positions.size()-2;i>=0;i--)owner=owner->childList(false)[positions[i]]; - } - //once we have the "original" object (hopefully) we look at who is referencing it - if(obj == owner)return false; - std::list todo(owner->hrefList); - todo.push_front(owner->parent); - while(!todo.empty()){ - SPObject* e = todo.front(); - todo.pop_front(); - if(!dynamic_cast(e))continue; - if(done.insert(e).second){ - if(e==obj){return false;} - todo.push_front(e->parent); - todo.insert(todo.begin(),e->hrefList.begin(),e->hrefList.end()); - } - } +bool URIReference::_acceptObject(SPObject *obj) const +{ + // we go back following hrefList and parent to find if the object already references ourselves indirectly + std::set done; + SPObject *owner = getOwner(); + if (!owner) + return true; + while (owner->cloned) { + std::vector positions; + while (owner->cloned) { + int position = 0; + SPObject *c = owner->parent->firstChild(); + while (c != owner && dynamic_cast(c)) { + position++; + c = c->next; + } + positions.push_back(position); + owner = owner->parent; + } + owner = ((SPUse *)owner)->get_original(); + for (int i = positions.size() - 2; i >= 0; i--) + owner = owner->childList(false)[positions[i]]; + } + // once we have the "original" object (hopefully) we look at who is referencing it + if (obj == owner) + return false; + std::list todo(owner->hrefList); + todo.push_front(owner->parent); + while (!todo.empty()) { + SPObject *e = todo.front(); + todo.pop_front(); + if (!dynamic_cast(e)) + continue; + if (done.insert(e).second) { + if (e == obj) { + return false; + } + todo.push_front(e->parent); + todo.insert(todo.begin(), e->hrefList.begin(), e->hrefList.end()); + } + } return true; } - void URIReference::attach(const URI &uri) throw(BadURIException) { SPDocument *document = NULL; @@ -109,32 +126,30 @@ void URIReference::attach(const URI &uri) throw(BadURIException) // PNG and JPG files are allowed (in the case of feImage). gchar *filename = uri.toString(); bool skip = false; - if( g_str_has_suffix( filename, ".jpg" ) || - g_str_has_suffix( filename, ".JPG" ) || - g_str_has_suffix( filename, ".png" ) || - g_str_has_suffix( filename, ".PNG" ) ) { + if (g_str_has_suffix(filename, ".jpg") || g_str_has_suffix(filename, ".JPG") || + g_str_has_suffix(filename, ".png") || g_str_has_suffix(filename, ".PNG")) { skip = true; } - + // The path contains references to separate document files to load. - if(document && uri.getPath() && !skip ) { + if (document && uri.getPath() && !skip) { std::string base = document->getBase() ? document->getBase() : ""; std::string path = uri.getFullPath(base); - if(!path.empty()) { + if (!path.empty()) { document = document->createChildDoc(path); } else { document = NULL; } } - if(!document) { + if (!document) { g_warning("Can't get document for referenced URI: %s", filename); - g_free( filename ); + g_free(filename); return; } - g_free( filename ); + g_free(filename); gchar const *fragment = uri.getFragment(); - if ( !uri.isRelative() || uri.getQuery() || !fragment ) { + if (!uri.isRelative() || uri.getQuery() || !fragment) { throw UnsupportedURIException(); } @@ -149,9 +164,9 @@ void URIReference::attach(const URI &uri) throw(BadURIException) the strlen calculation and validity testing to before strdup, and copying just the id without the "))". -- pjrm */ if (!strncmp(fragment, "xpointer(id(", 12)) { - id = g_strdup(fragment+12); + id = g_strdup(fragment + 12); size_t const len = strlen(id); - if ( len < 3 || strcmp(id+len-2, "))") ) { + if (len < 3 || strcmp(id + len - 2, "))")) { g_free(id); throw MalformedURIException(); } @@ -184,13 +199,14 @@ void URIReference::detach() void URIReference::_setObject(SPObject *obj) { - if ( obj && !_acceptObject(obj) ) { + if (obj && !_acceptObject(obj)) { obj = NULL; } - if ( obj == _obj ) return; + if (obj == _obj) + return; - SPObject *old_obj=_obj; + SPObject *old_obj = _obj; _obj = obj; _release_connection.disconnect(); @@ -211,7 +227,7 @@ void URIReference::_setObject(SPObject *obj) */ void URIReference::_release(SPObject *obj) { - g_assert( _obj == obj ); + g_assert(_obj == obj); _setObject(NULL); } @@ -219,28 +235,27 @@ void URIReference::_release(SPObject *obj) -SPObject* sp_css_uri_reference_resolve( SPDocument *document, const gchar *uri ) +SPObject *sp_css_uri_reference_resolve(SPDocument *document, const gchar *uri) { - SPObject* ref = NULL; + SPObject *ref = NULL; - if ( document && uri && ( strncmp(uri, "url(", 4) == 0 ) ) { - gchar *trimmed = extract_uri( uri ); - if ( trimmed ) { - ref = sp_uri_reference_resolve( document, trimmed ); - g_free( trimmed ); + if (document && uri && (strncmp(uri, "url(", 4) == 0)) { + gchar *trimmed = extract_uri(uri); + if (trimmed) { + ref = sp_uri_reference_resolve(document, trimmed); + g_free(trimmed); } } return ref; } -SPObject * -sp_uri_reference_resolve (SPDocument *document, const gchar *uri) +SPObject *sp_uri_reference_resolve(SPDocument *document, const gchar *uri) { - SPObject* ref = NULL; + SPObject *ref = NULL; - if ( uri && (*uri == '#') ) { - ref = document->getObjectById( uri + 1 ); + if (uri && (*uri == '#')) { + ref = document->getObjectById(uri + 1); } return ref; -- cgit v1.2.3 From f4ed6e3898b0e21cf131533bb9b4511ce82de86a Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Thu, 19 Nov 2015 22:15:59 +0100 Subject: fix for bug 1517740 (crash in some cases in selection sets) Fixed bugs: - https://launchpad.net/bugs/1517740 (bzr r14478) --- src/uri-references.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/uri-references.cpp') diff --git a/src/uri-references.cpp b/src/uri-references.cpp index b6ccdbf5f..db46a156f 100644 --- a/src/uri-references.cpp +++ b/src/uri-references.cpp @@ -19,7 +19,7 @@ #include "uri.h" #include "uri-references.h" #include "extract-uri.h" - +#include "sp-tag-use.h" #include #include @@ -84,7 +84,14 @@ bool URIReference::_acceptObject(SPObject *obj) const positions.push_back(position); owner = owner->parent; } - owner = ((SPUse *)owner)->get_original(); + if (dynamic_cast(owner)) + owner = ((SPUse *)owner)->get_original(); + else if (dynamic_cast(owner)) + owner = ((SPTagUse *)owner)->get_original(); + else { + g_warning("cloned object with no known type\n"); + return false; + } for (int i = positions.size() - 2; i >= 0; i--) owner = owner->childList(false)[positions[i]]; } -- cgit v1.2.3