The error macro should stop all processing, otherwise some NULL pointers might
get dereferenced (e.g. lex.c:1323). It uses setjmp/longjmp to return from
depths of the bison/lex routines. As obvious consequence, all memory allocated
in the parsers is lost and is never freed. Still, it should be better than
exit() I proposed before.

Changelog:
  - use setjmp/longjmp instead of exit()

Signed-off-by: Jan Safranek <jsafr...@redhat.com>
---

 src/config.c             |   12 +++++++++++-
 src/lex.l                |    7 ++++++-
 src/libcgroup-internal.h |    6 ++++++
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/src/config.c b/src/config.c
index 28519ff..bed3871 100644
--- a/src/config.c
+++ b/src/config.c
@@ -741,6 +741,7 @@ int cgroup_config_load_config(const char *pathname)
        int namespace_enabled = 0;
        int mount_enabled = 0;
        yyin = fopen(pathname, "re");
+       int ret;
 
        if (!yyin) {
                cgroup_dbg("Failed to open file %s\n", pathname);
@@ -754,7 +755,16 @@ int cgroup_config_load_config(const char *pathname)
 
        init_cgroup_table(config_cgroup_table, MAX_CGROUPS);
 
-       if (yyparse() != 0) {
+       /*
+        * Parser calls longjmp() on really fatal error (like out-of-memory).
+        */
+       ret = setjmp(parser_error_env);
+       if (!ret)
+               ret = yyparse();
+       if (ret) {
+               /*
+                * Either yyparse failed or longjmp() was called.
+                */
                cgroup_dbg("Failed to parse file %s\n", pathname);
                fclose(yyin);
                free(config_cgroup_table);
diff --git a/src/lex.l b/src/lex.l
index 8a99bbc..7a00015 100644
--- a/src/lex.l
+++ b/src/lex.l
@@ -17,8 +17,13 @@
 #include <libcgroup-internal.h>
 #include "parse.h"
 int line_no = 1;
+jmp_buf parser_error_env;
 
-#define YY_FATAL_ERROR(msg) fprintf(stderr, "%s\n", msg)
+#define YY_FATAL_ERROR(msg) \
+       do { \
+               fprintf(stderr, "%s\n", msg); \
+               longjmp(parser_error_env, 1); \
+       } while(0);
 %}
 
 %option nounput noinput
diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h
index de437e1..7d683f4 100644
--- a/src/libcgroup-internal.h
+++ b/src/libcgroup-internal.h
@@ -25,6 +25,7 @@ __BEGIN_DECLS
 #include <pthread.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <setjmp.h>
 
 /* Maximum number of mount points/controllers */
 #define MAX_MNT_ELEMENTS       8
@@ -185,6 +186,11 @@ struct cgroup_dictionary_iterator {
  */
 extern __thread int last_errno;
 
+/**
+ * 'Exception handler' for lex parser.
+ */
+extern jmp_buf parser_error_env;
+
 /* Internal API */
 char *cg_build_path(const char *name, char *path, const char *type);
 int cgroup_get_uid_gid_from_procfs(pid_t pid, uid_t *euid, gid_t *egid);


------------------------------------------------------------------------------
EMC VNX: the world's simplest storage, starting under $10K
The only unified storage solution that offers unified management 
Up to 160% more powerful than alternatives and 25% more efficient. 
Guaranteed. http://p.sf.net/sfu/emc-vnx-dev2dev
_______________________________________________
Libcg-devel mailing list
Libcg-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libcg-devel

Reply via email to