Commit 7261f404d201b157dc0ce1ae0386fd74f3a128a7

Ran Benita 2012-10-29T01:00:27

state, context: allow passing NULL to *_unref() For error handling code, it's nice to be able to pass NULL to these function without worrying about segfaults ensuing. free() sets the precedent here. Also document this fact. Signed-off-by: Ran Benita <ran234@gmail.com>

diff --git a/src/context.c b/src/context.c
index 53028a1..a846b8f 100644
--- a/src/context.c
+++ b/src/context.c
@@ -206,7 +206,7 @@ xkb_context_ref(struct xkb_context *ctx)
 XKB_EXPORT void
 xkb_context_unref(struct xkb_context *ctx)
 {
-    if (--ctx->refcnt > 0)
+    if (!ctx || --ctx->refcnt > 0)
         return;
 
     xkb_context_include_path_clear(ctx);
diff --git a/src/state.c b/src/state.c
index eaa1f10..48b2132 100644
--- a/src/state.c
+++ b/src/state.c
@@ -583,7 +583,7 @@ xkb_state_ref(struct xkb_state *state)
 XKB_EXPORT void
 xkb_state_unref(struct xkb_state *state)
 {
-    if (--state->refcnt > 0)
+    if (!state || --state->refcnt > 0)
         return;
 
     xkb_keymap_unref(state->keymap);
diff --git a/test/state.c b/test/state.c
index d23b94c..83a8f45 100644
--- a/test/state.c
+++ b/test/state.c
@@ -339,6 +339,11 @@ main(void)
 
     assert(context);
 
+    /* Make sure these are allowed. */
+    xkb_context_unref(NULL);
+    xkb_keymap_unref(NULL);
+    xkb_state_unref(NULL);
+
     keymap = test_compile_rules(context, "evdev", "pc104", "us,ru", NULL, "grp:menu_toggle");
     assert(keymap);
 
diff --git a/xkbcommon/xkbcommon.h b/xkbcommon/xkbcommon.h
index fe5c789..65c4dcc 100644
--- a/xkbcommon/xkbcommon.h
+++ b/xkbcommon/xkbcommon.h
@@ -439,6 +439,8 @@ xkb_context_ref(struct xkb_context *context);
 /**
  * Release a reference on a context, and possibly free it.
  *
+ * @param context The context.  If it is NULL, this function does nothing.
+ *
  * @memberof xkb_context
  */
 void
@@ -737,6 +739,8 @@ xkb_keymap_ref(struct xkb_keymap *keymap);
 /**
  * Release a reference on a keymap, and possibly free it.
  *
+ * @param keymap The keymap.  If it is NULL, this function does nothing.
+ *
  * @memberof xkb_keymap
  */
 void
@@ -991,6 +995,8 @@ xkb_state_ref(struct xkb_state *state);
 /**
  * Release a reference on a keybaord state object, and possibly free it.
  *
+ * @param state The state.  If it is NULL, this function does nothing.
+ *
  * @memberof xkb_state
  */
 void