Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/rpm-software-management/createrepo_c.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleš Matěj <amatej@redhat.com>2021-11-10 15:07:39 +0300
committerNeal Gompa (ニール・ゴンパ) <ngompa13@gmail.com>2022-03-29 07:53:40 +0300
commit0b2f0180bf777aea2255eaa2af27d4e82055ec33 (patch)
tree6c1c25dd9b9d08dada7095c487ba6c0f02ea97d7
parent869b789f0f4eedfab561f7d397a578cbc5966ed9 (diff)
Fix '&' encoding in attributes when parsing repodata
When loading repodata libxml2 replaces all '&' with "&#38;" This can lead to problems, if an rpm contains '&' in a dependency and we run createrepo_c on it it gets stored as "&amp;" if we later run createrepo_c with --update its loaded and encoded as "&#38;" which get stored in the xml as "&amp;#38;" To circumvent this change all "&#38;" back to '&' when parsing.
-rw-r--r--src/xml_parser.c44
-rw-r--r--src/xml_parser_filelists.c7
-rw-r--r--src/xml_parser_internal.h9
-rw-r--r--src/xml_parser_other.c7
-rw-r--r--src/xml_parser_primary.c7
-rw-r--r--src/xml_parser_repomd.c7
-rw-r--r--src/xml_parser_updateinfo.c7
7 files changed, 88 insertions, 0 deletions
diff --git a/src/xml_parser.c b/src/xml_parser.c
index 05bcde7..37203ef 100644
--- a/src/xml_parser.c
+++ b/src/xml_parser.c
@@ -292,3 +292,47 @@ cr_xml_parser_generic_from_string(xmlParserCtxtPtr parser,
return ret;
}
+
+const xmlChar **
+unescape_ampersand_from_values(const xmlChar **attr, gboolean *allocation_needed) {
+ *allocation_needed = FALSE;
+
+ if (!attr) {
+ return attr;
+ }
+
+ // In the vast majority of cases there is no '&' in the
+ // data so check if there is any first and if not return
+ // quickly.
+ //
+ // attr consists of key1, value1, key2, value2 pairs,
+ // we know which keys we want (they don't contain &) so
+ // we don't have to check those.
+ size_t nattr;
+ for (nattr = 1; attr[nattr]; nattr+=2) {
+ if (strchr((char *)attr[nattr], '&')) {
+ *allocation_needed = TRUE;
+ }
+ }
+
+ if (!*allocation_needed) {
+ return attr;
+ }
+
+ char **attr_copy = g_malloc0(sizeof(char *) * (nattr - 1));
+ if (attr_copy) {
+ for (nattr = 0; attr[nattr]; nattr++) {
+ if (strchr((char *)attr[nattr], '&')) {
+ char **cut_out_amp = g_strsplit((char *)attr[nattr], "#38;", -1);
+ attr_copy[nattr] = g_strjoinv(NULL, cut_out_amp);
+ g_strfreev(cut_out_amp);
+ } else {
+ attr_copy[nattr] = g_strdup((char *)attr[nattr]);
+ }
+ }
+
+ attr_copy[nattr] = 0;
+ }
+
+ return (const xmlChar **)attr_copy;
+}
diff --git a/src/xml_parser_filelists.c b/src/xml_parser_filelists.c
index 33a2058..1885850 100644
--- a/src/xml_parser_filelists.c
+++ b/src/xml_parser_filelists.c
@@ -90,6 +90,9 @@ cr_start_handler(void *pdata, const xmlChar *element, const xmlChar **attr)
return;
}
+ gboolean free_attr = FALSE;
+ attr = unescape_ampersand_from_values(attr, &free_attr);
+
// Update parser data
pd->state = sw->to;
pd->docontent = sw->docontent;
@@ -197,6 +200,10 @@ cr_start_handler(void *pdata, const xmlChar *element, const xmlChar **attr)
default:
break;
}
+
+ if (free_attr) {
+ g_strfreev((char **)attr);
+ }
}
static void XMLCALL
diff --git a/src/xml_parser_internal.h b/src/xml_parser_internal.h
index f81566b..0a33578 100644
--- a/src/xml_parser_internal.h
+++ b/src/xml_parser_internal.h
@@ -249,6 +249,15 @@ other_parser_data_new(cr_XmlParserNewPkgCb newpkgcb,
cr_XmlParserWarningCb warningcb,
void *warningcb_data);
+/** Replace &#38; by real ampersand char from values in attr.
+ * @param attr List of attributes
+ * @param allocation_needed Output bool whether returned attr has to be freed.
+ * @return attr with regular '&' instead of "&#38";
+ */
+const xmlChar **unescape_ampersand_from_values(const xmlChar **attr,
+ gboolean *allocation_needed);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/src/xml_parser_other.c b/src/xml_parser_other.c
index a57382a..a5d8afa 100644
--- a/src/xml_parser_other.c
+++ b/src/xml_parser_other.c
@@ -90,6 +90,9 @@ cr_start_handler(void *pdata, const xmlChar *element, const xmlChar **attr)
return;
}
+ gboolean free_attr = FALSE;
+ attr = unescape_ampersand_from_values(attr, &free_attr);
+
// Update parser data
pd->state = sw->to;
pd->docontent = sw->docontent;
@@ -206,6 +209,10 @@ cr_start_handler(void *pdata, const xmlChar *element, const xmlChar **attr)
default:
break;
}
+
+ if (free_attr) {
+ g_strfreev((char **)attr);
+ }
}
static void XMLCALL
diff --git a/src/xml_parser_primary.c b/src/xml_parser_primary.c
index d3d3f5d..a98ecf9 100644
--- a/src/xml_parser_primary.c
+++ b/src/xml_parser_primary.c
@@ -156,6 +156,9 @@ cr_start_handler(void *pdata, const xmlChar *element, const xmlChar **attr)
return;
}
+ gboolean free_attr = FALSE;
+ attr = unescape_ampersand_from_values(attr, &free_attr);
+
// Update parser data
pd->state = sw->to;
pd->docontent = sw->docontent;
@@ -444,6 +447,10 @@ cr_start_handler(void *pdata, const xmlChar *element, const xmlChar **attr)
default:
break;
}
+
+ if (free_attr) {
+ g_strfreev((char **)attr);
+ }
}
static void XMLCALL
diff --git a/src/xml_parser_repomd.c b/src/xml_parser_repomd.c
index 2e31817..f0b06a5 100644
--- a/src/xml_parser_repomd.c
+++ b/src/xml_parser_repomd.c
@@ -114,6 +114,9 @@ cr_start_handler(void *pdata, const xmlChar *element, const xmlChar **attr)
return;
}
+ gboolean free_attr = FALSE;
+ attr = unescape_ampersand_from_values(attr, &free_attr);
+
// Update parser data
pd->state = sw->to;
pd->docontent = sw->docontent;
@@ -258,6 +261,10 @@ cr_start_handler(void *pdata, const xmlChar *element, const xmlChar **attr)
default:
break;
}
+
+ if (free_attr) {
+ g_strfreev((char **)attr);
+ }
}
static void
diff --git a/src/xml_parser_updateinfo.c b/src/xml_parser_updateinfo.c
index e51929b..6635930 100644
--- a/src/xml_parser_updateinfo.c
+++ b/src/xml_parser_updateinfo.c
@@ -132,6 +132,9 @@ cr_start_handler(void *pdata, const xmlChar *element, const xmlChar **attr)
return;
}
+ gboolean free_attr = FALSE;
+ attr = unescape_ampersand_from_values(attr, &free_attr);
+
// Update parser data
pd->state = sw->to;
pd->docontent = sw->docontent;
@@ -394,6 +397,10 @@ cr_start_handler(void *pdata, const xmlChar *element, const xmlChar **attr)
package->relogin_suggested = TRUE;
break;
}
+
+ if (free_attr) {
+ g_strfreev((char **)attr);
+ }
}
static void