diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 116c50e8..47f351d2 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -118,6 +118,7 @@ ostree_checksum_b64_inplace_from_bytes ostree_checksum_b64_inplace_to_bytes ostree_cmp_checksum_bytes ostree_validate_rev +ostree_validate_remote_name ostree_parse_refspec ostree_object_type_to_string ostree_object_type_from_string diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym index a9c3f610..d2bc8399 100644 --- a/src/libostree/libostree-devel.sym +++ b/src/libostree/libostree-devel.sym @@ -19,7 +19,9 @@ /* Add new symbols here. Release commits should copy this section into -released.sym. */ LIBOSTREE_2017.8 { -}; +global: + ostree_validate_remote_name; +} LIBOSTREE_2017.7; /* Stub section for the stable release *after* this development one; don't * edit this other than to update the last number. This is just a copy/paste diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index 54e01bcb..3eb35c3f 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -101,6 +101,7 @@ ostree_validate_checksum_string (const char *sha256, #define OSTREE_REF_FRAGMENT_REGEXP "[-._\\w\\d]+" #define OSTREE_REF_REGEXP "(?:" OSTREE_REF_FRAGMENT_REGEXP "/)*" OSTREE_REF_FRAGMENT_REGEXP +#define OSTREE_REMOTE_NAME_REGEXP OSTREE_REF_FRAGMENT_REGEXP /** * ostree_parse_refspec: @@ -125,7 +126,7 @@ ostree_parse_refspec (const char *refspec, static gsize regex_initialized; if (g_once_init_enter (®ex_initialized)) { - regex = g_regex_new ("^(" OSTREE_REF_FRAGMENT_REGEXP ":)?(" OSTREE_REF_REGEXP ")$", 0, 0, NULL); + regex = g_regex_new ("^(" OSTREE_REMOTE_NAME_REGEXP ":)?(" OSTREE_REF_REGEXP ")$", 0, 0, NULL); g_assert (regex); g_once_init_leave (®ex_initialized, 1); } @@ -180,6 +181,35 @@ ostree_validate_rev (const char *rev, return TRUE; } +/** + * ostree_validate_remote_name: + * @remote_name: A remote name + * @error: Error + * + * Returns: %TRUE if @remote_name is a valid remote name + * Since: 2017.7 + */ +gboolean +ostree_validate_remote_name (const char *remote_name, + GError **error) +{ + g_autoptr(GMatchInfo) match = NULL; + + static gsize regex_initialized; + static GRegex *regex; + if (g_once_init_enter (®ex_initialized)) + { + regex = g_regex_new ("^" OSTREE_REMOTE_NAME_REGEXP "$", 0, 0, NULL); + g_assert (regex); + g_once_init_leave (®ex_initialized, 1); + } + + if (!g_regex_match (regex, remote_name, 0, &match)) + return glnx_throw (error, "Invalid remote name %s", remote_name); + + return TRUE; +} + GVariant * _ostree_file_header_new (GFileInfo *file_info, GVariant *xattrs) diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h index c1e014e2..dc64d89b 100644 --- a/src/libostree/ostree-core.h +++ b/src/libostree/ostree-core.h @@ -242,6 +242,9 @@ int ostree_cmp_checksum_bytes (const guchar *a, const guchar *b); _OSTREE_PUBLIC gboolean ostree_validate_rev (const char *rev, GError **error); +_OSTREE_PUBLIC +gboolean ostree_validate_remote_name (const char *remote_name, GError **error); + _OSTREE_PUBLIC gboolean ostree_parse_refspec (const char *refspec, char **out_remote, diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index e556e464..6bcc8e0d 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -876,8 +876,8 @@ impl_repo_remote_add (OstreeRepo *self, g_return_val_if_fail (url != NULL, FALSE); g_return_val_if_fail (options == NULL || g_variant_is_of_type (options, G_VARIANT_TYPE ("a{sv}")), FALSE); - if (strchr (name, '/') != NULL) - return glnx_throw (error, "Invalid character '/' in remote name: %s", name); + if (!ostree_validate_remote_name (name, error)) + return FALSE; g_autoptr(OstreeRemote) remote = _ostree_repo_get_remote (self, name, NULL); if (remote != NULL && if_not_exists) @@ -1005,8 +1005,8 @@ impl_repo_remote_delete (OstreeRepo *self, { g_return_val_if_fail (name != NULL, FALSE); - if (strchr (name, '/') != NULL) - return glnx_throw (error, "Invalid character '/' in remote name: %s", name); + if (!ostree_validate_remote_name (name, error)) + return FALSE; g_autoptr(OstreeRemote) remote = NULL; if (if_exists) diff --git a/tests/test-basic-c.c b/tests/test-basic-c.c index dbab087e..dc6d33f2 100644 --- a/tests/test-basic-c.c +++ b/tests/test-basic-c.c @@ -185,6 +185,25 @@ static gboolean hi_content_stream_new (GInputStream **out_stream, return ostree_raw_file_to_content_stream ((GInputStream*)hi_memstream, finfo, NULL, out_stream, out_length, NULL, error); } +static void +test_validate_remotename (void) +{ + const char *valid[] = {"foo", "hello-world"}; + const char *invalid[] = {"foo/bar", ""}; + for (guint i = 0; i < G_N_ELEMENTS(valid); i++) + { + g_autoptr(GError) error = NULL; + g_assert (ostree_validate_remote_name (valid[i], &error)); + g_assert_no_error (error); + } + for (guint i = 0; i < G_N_ELEMENTS(invalid); i++) + { + g_autoptr(GError) error = NULL; + g_assert (!ostree_validate_remote_name (invalid[i], &error)); + g_assert (error != NULL); + } +} + static void test_object_writes (gconstpointer data) { @@ -232,6 +251,7 @@ int main (int argc, char **argv) g_test_add_data_func ("/repo-not-system", repo, test_repo_is_not_system); g_test_add_data_func ("/raw-file-to-archive-z2-stream", repo, test_raw_file_to_archive_z2_stream); g_test_add_data_func ("/objectwrites", repo, test_object_writes); + g_test_add_func ("/remotename", test_validate_remotename); return g_test_run(); out: