int snd_input_getc(snd_input_t *input);
int snd_input_ungetc(snd_input_t *input, int c);
+int snd_relative_path_check(const char *path);
+
/** \} */
#ifdef __cplusplus
if (file[0] == '/')
return snd_input_stdio_open(inputp, file, "r");
+ err = snd_relative_path_check(file);
+ if (err < 0) {
+ snd_error(CONFIG, "Include file path '%s' escapes the include directory", file);
+ return err;
+ }
+
/* search file in user specified include paths. These directories
* are subdirectories of /usr/share/alsa.
*/
return 0;
}
+/*
+ * \brief Verify that a relative path does not escape its base directory via ".." components.
+ * \param path Relative path to check.
+ * \return Zero if successful, otherwise -EINVAL.
+ *
+ * The check is purely lexical.
+ *
+ * Examples (base = root directory):
+ * a/../b -> allowed (depth: 1, 0, 1)
+ * ../b -> rejected (depth: -1)
+ * a/b/c/../d/../../../../../x -> rejected
+ */
+int snd_relative_path_check(const char *path)
+{
+ const char *p = path;
+ int depth = 0;
+
+ while (*p) {
+ const char *comp = p;
+ size_t len;
+
+ while (*p && *p != '/')
+ p++;
+ len = p - comp;
+
+ while (*p == '/')
+ p++;
+
+ if (len == 0)
+ continue;
+ if (len == 1 && comp[0] == '.')
+ continue;
+ if (len == 2 && comp[0] == '.' && comp[1] == '.') {
+ if (--depth < 0)
+ return -EINVAL;
+ continue;
+ }
+ depth++;
+ }
+
+ return 0;
+}