aboutsummaryrefslogtreecommitdiff
path: root/gcc/diagnostic-format-json.cc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2019-05-23 00:42:03 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2019-05-23 00:42:03 +0000
commit30d3ba5142311df568e8f62a374d83d0bdab42bf (patch)
tree94063ddaab8d31b6e0f1b5ab9eb9870683948b21 /gcc/diagnostic-format-json.cc
parentcf9219c7420320986f9bcd956b04b95a51ebac49 (diff)
downloadgcc-30d3ba5142311df568e8f62a374d83d0bdab42bf.zip
gcc-30d3ba5142311df568e8f62a374d83d0bdab42bf.tar.gz
gcc-30d3ba5142311df568e8f62a374d83d0bdab42bf.tar.bz2
Bulletproof -fdiagnostics-format=json against bad locations (PR c++/90462)
PR c++/90462 reports an ICE with -fdiagnostics-format=json when attempting to serialize a malformed location to JSON. The compound location_t in question has meaningful "caret" and "start" locations, but has UNKNOWN_LOCATION for its "finish" location, leading to a NULL pointer dereference when attempting to build a JSON string for the filename. This patch bulletproofs the JSON output so that attempts to write a JSON object for a location with a NULL file will lead to an object with no "file" key, and attempts to write a compound location with UNKNOWN_LOCATION for its start or finish will lead to the corresponding JSON child object being omitted. This patch also adds a json::object::get member function, for self-testing the above. gcc/ChangeLog: PR c++/90462 * diagnostic-format-json.cc: Include "selftest.h". (json_from_expanded_location): Only add "file" key for non-NULL file strings. (json_from_location_range): Don't add "start" and "finish" children if they are UNKNOWN_LOCATION. (selftest::test_unknown_location): New selftest. (selftest::test_bad_endpoints): New selftest. (selftest::diagnostic_format_json_cc_tests): New function. * json.cc (json::object::get): New function. (selftest::test_object_get): New selftest. (selftest::json_cc_tests): Call it. * json.h (json::object::get): New decl. * selftest-run-tests.c (selftest::run_tests): Call selftest::diagnostic_format_json_cc_tests. * selftest.h (selftest::diagnostic_format_json_cc_tests): New decl. gcc/testsuite/ChangeLog: PR c++/90462 * g++.dg/pr90462.C: New test. From-SVN: r271535
Diffstat (limited to 'gcc/diagnostic-format-json.cc')
-rw-r--r--gcc/diagnostic-format-json.cc60
1 files changed, 57 insertions, 3 deletions
diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index 0355210..53c3b63 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "diagnostic.h"
#include "json.h"
+#include "selftest.h"
/* The top-level JSON array of pending diagnostics. */
@@ -45,7 +46,8 @@ json_from_expanded_location (location_t loc)
{
expanded_location exploc = expand_location (loc);
json::object *result = new json::object ();
- result->set ("file", new json::string (exploc.file));
+ if (exploc.file)
+ result->set ("file", new json::string (exploc.file));
result->set ("line", new json::number (exploc.line));
result->set ("column", new json::number (exploc.column));
return result;
@@ -66,9 +68,11 @@ json_from_location_range (const location_range *loc_range, unsigned range_idx)
json::object *result = new json::object ();
result->set ("caret", json_from_expanded_location (caret_loc));
- if (start_loc != caret_loc)
+ if (start_loc != caret_loc
+ && start_loc != UNKNOWN_LOCATION)
result->set ("start", json_from_expanded_location (start_loc));
- if (finish_loc != caret_loc)
+ if (finish_loc != caret_loc
+ && finish_loc != UNKNOWN_LOCATION)
result->set ("finish", json_from_expanded_location (finish_loc));
if (loc_range->m_label)
@@ -262,3 +266,53 @@ diagnostic_output_format_init (diagnostic_context *context,
break;
}
}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* We shouldn't call json_from_expanded_location on UNKNOWN_LOCATION,
+ but verify that we handle this gracefully. */
+
+static void
+test_unknown_location ()
+{
+ delete json_from_expanded_location (UNKNOWN_LOCATION);
+}
+
+/* Verify that we gracefully handle attempts to serialize bad
+ compound locations. */
+
+static void
+test_bad_endpoints ()
+{
+ location_t bad_endpoints
+ = make_location (BUILTINS_LOCATION,
+ UNKNOWN_LOCATION, UNKNOWN_LOCATION);
+
+ location_range loc_range;
+ loc_range.m_loc = bad_endpoints;
+ loc_range.m_range_display_kind = SHOW_RANGE_WITH_CARET;
+ loc_range.m_label = NULL;
+
+ json::object *obj = json_from_location_range (&loc_range, 0);
+ /* We should have a "caret" value, but no "start" or "finish" values. */
+ ASSERT_TRUE (obj != NULL);
+ ASSERT_TRUE (obj->get ("caret") != NULL);
+ ASSERT_TRUE (obj->get ("start") == NULL);
+ ASSERT_TRUE (obj->get ("finish") == NULL);
+ delete obj;
+}
+
+/* Run all of the selftests within this file. */
+
+void
+diagnostic_format_json_cc_tests ()
+{
+ test_unknown_location ();
+ test_bad_endpoints ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */