diff mbox

[jit] Verify enum values earlier

Message ID 1415210151-3228-1-git-send-email-dmalcolm@redhat.com
State New
Headers show

Commit Message

David Malcolm Nov. 5, 2014, 5:55 p.m. UTC
It wasn't clear to me that all of these enum values were being fully
validated by the internals, and it's better to fail early (so we can
report which function was at fault), so explicitly validate enum values
at the API entrypoints.

The new testcases bring the # of expected passes in jit.sum from
4663 to 4711.

Committed to the dmalcolm/jit branch.

gcc/jit/ChangeLog.jit:
	* libgccjit.c (gcc_jit_context_get_type): Verify that "type"
	is valid immediately, rather than relying on called code.
	(gcc_jit_context_new_function): Likewise for "kind".
	(gcc_jit_context_new_unary_op): Likewise for "op".
	(valid_binary_op_p): New.
	(gcc_jit_context_new_binary_op): Verify that "op" is valid
	immediately, rather than relying on called code.
	(gcc_jit_context_new_comparison): Likewise.
	(gcc_jit_block_add_assignment_op): Likewise.

gcc/testsuite/ChangeLog.jit:
	* jit.dg/test-error-get-type-bad-enum.c: New test case.
	* jit.dg/test-error-new-binary-op-bad-op.c: Likewise.
	* jit.dg/test-error-new-function-bad-kind.c: Likewise.
	* jit.dg/test-error-new-unary-op-bad-op.c: Likewise.
---
 gcc/jit/ChangeLog.jit                              | 12 ++++++
 gcc/jit/libgccjit.c                                | 49 +++++++++++++++++++---
 gcc/testsuite/ChangeLog.jit                        |  7 ++++
 .../jit.dg/test-error-get-type-bad-enum.c          | 27 ++++++++++++
 .../jit.dg/test-error-new-binary-op-bad-op.c       | 37 ++++++++++++++++
 .../jit.dg/test-error-new-function-bad-kind.c      | 41 ++++++++++++++++++
 .../jit.dg/test-error-new-unary-op-bad-op.c        | 36 ++++++++++++++++
 7 files changed, 204 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/jit.dg/test-error-get-type-bad-enum.c
 create mode 100644 gcc/testsuite/jit.dg/test-error-new-binary-op-bad-op.c
 create mode 100644 gcc/testsuite/jit.dg/test-error-new-function-bad-kind.c
 create mode 100644 gcc/testsuite/jit.dg/test-error-new-unary-op-bad-op.c
diff mbox

Patch

diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index 3d6361c..ce927d6 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,5 +1,17 @@ 
 2014-11-05  David Malcolm  <dmalcolm@redhat.com>
 
+	* libgccjit.c (gcc_jit_context_get_type): Verify that "type"
+	is valid immediately, rather than relying on called code.
+	(gcc_jit_context_new_function): Likewise for "kind".
+	(gcc_jit_context_new_unary_op): Likewise for "op".
+	(valid_binary_op_p): New.
+	(gcc_jit_context_new_binary_op): Verify that "op" is valid
+	immediately, rather than relying on called code.
+	(gcc_jit_context_new_comparison): Likewise.
+	(gcc_jit_block_add_assignment_op): Likewise.
+
+2014-11-05  David Malcolm  <dmalcolm@redhat.com>
+
 	* libgccjit.c: Include safe-ctype.h from libiberty.
 	(IS_ASCII_ALPHA): Delete.
 	(IS_ASCII_DIGIT): Delete.
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index d9f259e..c109ba6 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -316,7 +316,11 @@  gcc_jit_context_get_type (gcc_jit_context *ctxt,
 			  enum gcc_jit_types type)
 {
   RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
-  /* The inner function checks "type" for us.  */
+  RETURN_NULL_IF_FAIL_PRINTF1 (
+    (type >= GCC_JIT_TYPE_VOID
+     && type <= GCC_JIT_TYPE_FILE_PTR),
+    ctxt, NULL,
+    "unrecognized value for enum gcc_jit_types: %i", type);
 
   return (gcc_jit_type *)ctxt->get_type (type);
 }
@@ -574,6 +578,12 @@  gcc_jit_context_new_function (gcc_jit_context *ctxt,
 			      int is_variadic)
 {
   RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
+  RETURN_NULL_IF_FAIL_PRINTF1 (
+    ((kind >= GCC_JIT_FUNCTION_EXPORTED)
+     && (kind <= GCC_JIT_FUNCTION_ALWAYS_INLINE)),
+    ctxt, loc,
+    "unrecognized value for enum gcc_jit_function_kind: %i",
+    kind);
   RETURN_NULL_IF_FAIL (return_type, ctxt, loc, "NULL return_type");
   RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name");
   /* The assembler can only handle certain names, so for now, enforce
@@ -835,13 +845,29 @@  gcc_jit_context_new_unary_op (gcc_jit_context *ctxt,
 			      gcc_jit_rvalue *rvalue)
 {
   RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
-  /* op is checked by the inner function.  */
+  RETURN_NULL_IF_FAIL_PRINTF1 (
+    (op >= GCC_JIT_UNARY_OP_MINUS
+     && op <= GCC_JIT_UNARY_OP_LOGICAL_NEGATE),
+    ctxt, loc,
+    "unrecognized value for enum gcc_jit_unary_op: %i",
+    op);
   RETURN_NULL_IF_FAIL (result_type, ctxt, loc, "NULL result_type");
   RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
 
   return (gcc_jit_rvalue *)ctxt->new_unary_op (loc, op, result_type, rvalue);
 }
 
+/* Determine if OP is a valid value for enum gcc_jit_binary_op.
+   For use by both gcc_jit_context_new_binary_op and
+   gcc_jit_block_add_assignment_op.  */
+
+static bool
+valid_binary_op_p (enum gcc_jit_binary_op op)
+{
+  return (op >= GCC_JIT_BINARY_OP_PLUS
+	  && op <= GCC_JIT_BINARY_OP_RSHIFT);
+}
+
 gcc_jit_rvalue *
 gcc_jit_context_new_binary_op (gcc_jit_context *ctxt,
 			       gcc_jit_location *loc,
@@ -850,7 +876,11 @@  gcc_jit_context_new_binary_op (gcc_jit_context *ctxt,
 			       gcc_jit_rvalue *a, gcc_jit_rvalue *b)
 {
   RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
-  /* op is checked by the inner function.  */
+  RETURN_NULL_IF_FAIL_PRINTF1 (
+    valid_binary_op_p (op),
+    ctxt, loc,
+    "unrecognized value for enum gcc_jit_binary_op: %i",
+    op);
   RETURN_NULL_IF_FAIL (result_type, ctxt, loc, "NULL result_type");
   RETURN_NULL_IF_FAIL (a, ctxt, loc, "NULL a");
   RETURN_NULL_IF_FAIL (b, ctxt, loc, "NULL b");
@@ -874,7 +904,12 @@  gcc_jit_context_new_comparison (gcc_jit_context *ctxt,
 				gcc_jit_rvalue *a, gcc_jit_rvalue *b)
 {
   RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
-  /* op is checked by the inner function.  */
+  RETURN_NULL_IF_FAIL_PRINTF1 (
+    (op >= GCC_JIT_COMPARISON_EQ
+     && op <= GCC_JIT_COMPARISON_GE),
+    ctxt, loc,
+    "unrecognized value for enum gcc_jit_comparison: %i",
+    op);
   RETURN_NULL_IF_FAIL (a, ctxt, loc, "NULL a");
   RETURN_NULL_IF_FAIL (b, ctxt, loc, "NULL b");
   RETURN_NULL_IF_FAIL_PRINTF4 (
@@ -1281,7 +1316,11 @@  gcc_jit_block_add_assignment_op (gcc_jit_block *block,
   RETURN_IF_NOT_VALID_BLOCK (block, loc);
   gcc::jit::recording::context *ctxt = block->get_context ();
   RETURN_IF_FAIL (lvalue, ctxt, loc, "NULL lvalue");
-  /* FIXME: op is checked by new_binary_op */
+  RETURN_IF_FAIL_PRINTF1 (
+    valid_binary_op_p (op),
+    ctxt, loc,
+    "unrecognized value for enum gcc_jit_binary_op: %i",
+    op);
   RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
 
   return block->add_assignment_op (loc, lvalue, op, rvalue);
diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit
index 2d6acdb..a850c6f 100644
--- a/gcc/testsuite/ChangeLog.jit
+++ b/gcc/testsuite/ChangeLog.jit
@@ -1,3 +1,10 @@ 
+2014-11-05  David Malcolm  <dmalcolm@redhat.com>
+
+	* jit.dg/test-error-get-type-bad-enum.c: New test case.
+	* jit.dg/test-error-new-binary-op-bad-op.c: Likewise.
+	* jit.dg/test-error-new-function-bad-kind.c: Likewise.
+	* jit.dg/test-error-new-unary-op-bad-op.c: Likewise.
+
 2014-10-22  David Malcolm  <dmalcolm@redhat.com>
 
 	* jit.dg/jit.exp (DEFAULT_CFLAGS): Add -fgnu89-inline since
diff --git a/gcc/testsuite/jit.dg/test-error-get-type-bad-enum.c b/gcc/testsuite/jit.dg/test-error-get-type-bad-enum.c
new file mode 100644
index 0000000..67b712e
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-get-type-bad-enum.c
@@ -0,0 +1,27 @@ 
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Trigger an API error by passing bad data.  */
+  gcc_jit_context_get_type (ctxt, 42);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted.  */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      ("gcc_jit_context_get_type:"
+		       " unrecognized value for enum gcc_jit_types: 42"));
+}
+
diff --git a/gcc/testsuite/jit.dg/test-error-new-binary-op-bad-op.c b/gcc/testsuite/jit.dg/test-error-new-binary-op-bad-op.c
new file mode 100644
index 0000000..0592f55
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-new-binary-op-bad-op.c
@@ -0,0 +1,37 @@ 
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Trigger an API error by passing bad data.  */
+  (void)gcc_jit_context_new_binary_op (
+	  ctxt,
+	  NULL,
+
+	  /* Non-valid enum value: */
+	  (enum gcc_jit_binary_op) 42,
+
+	  /* These aren't valid either: */
+	  NULL, /* gcc_jit_type *result_type, */
+	  NULL, NULL); /* gcc_jit_rvalue *a, gcc_jit_rvalue *b */
+
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted.  */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      ("gcc_jit_context_new_binary_op:"
+		       " unrecognized value for enum gcc_jit_binary_op: 42"));
+}
+
diff --git a/gcc/testsuite/jit.dg/test-error-new-function-bad-kind.c b/gcc/testsuite/jit.dg/test-error-new-function-bad-kind.c
new file mode 100644
index 0000000..f9772de
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-new-function-bad-kind.c
@@ -0,0 +1,41 @@ 
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *int_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+  /* Trigger an API error by passing bad data.  */
+  (void)gcc_jit_context_new_function (
+	  ctxt,
+	  NULL,
+
+	  /* Non-valid enum value: */
+	  (enum gcc_jit_function_kind)42,
+
+	  int_type, /* gcc_jit_type *return_type, */
+	  "foo", /* const char *name, */
+	  0, /* int num_params, */
+	  NULL, /* gcc_jit_param **params, */
+	  0); /* int is_variadic */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted.  */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      ("gcc_jit_context_new_function:"
+		       " unrecognized value for enum gcc_jit_function_kind: 42"));
+}
+
diff --git a/gcc/testsuite/jit.dg/test-error-new-unary-op-bad-op.c b/gcc/testsuite/jit.dg/test-error-new-unary-op-bad-op.c
new file mode 100644
index 0000000..faab139
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-new-unary-op-bad-op.c
@@ -0,0 +1,36 @@ 
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Trigger an API error by passing bad data.  */
+  (void)gcc_jit_context_new_unary_op (
+	  ctxt,
+	  NULL,
+
+	  /* Non-valid enum value: */
+	  (enum gcc_jit_unary_op) 42,
+
+	  /* These aren't valid either: */
+	  NULL, /* gcc_jit_type *result_type, */
+	  NULL); /* gcc_jit_rvalue *rvalue */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  /* Ensure that the bad API usage prevents the API giving a bogus
+     result back.  */
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted.  */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      ("gcc_jit_context_new_unary_op:"
+		       " unrecognized value for enum gcc_jit_unary_op: 42"));
+}
+