From 11a934d427502f917dbbf47b088d9abde186c0a7 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 16 Jun 2017 11:03:51 -0700 Subject: [PATCH] Fix segfault on edge with no inputs PR #1281 added a deference of most_recent_input without checking for NULL, which can occur if a build rule has no inputs. Check it for null before dereferencing, and add a test. Fixes #1290. --- src/build_test.cc | 31 +++++++++++++++++++++++++++++++ src/graph.cc | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/build_test.cc b/src/build_test.cc index 0eb9aaa36f..623ed14c42 100644 --- a/src/build_test.cc +++ b/src/build_test.cc @@ -1305,6 +1305,37 @@ TEST_F(BuildWithLogTest, RebuildAfterFailure) { EXPECT_EQ("", err); } +TEST_F(BuildWithLogTest, RebuildWithNoInputs) { + ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, +"rule touch\n" +" command = touch\n" +"build out1: touch\n" +"build out2: touch in\n")); + + string err; + + fs_.Create("in", ""); + + EXPECT_TRUE(builder_.AddTarget("out1", &err)); + EXPECT_TRUE(builder_.AddTarget("out2", &err)); + EXPECT_TRUE(builder_.Build(&err)); + EXPECT_EQ("", err); + EXPECT_EQ(2u, command_runner_.commands_ran_.size()); + + command_runner_.commands_ran_.clear(); + state_.Reset(); + + fs_.Tick(); + + fs_.Create("in", ""); + + EXPECT_TRUE(builder_.AddTarget("out1", &err)); + EXPECT_TRUE(builder_.AddTarget("out2", &err)); + EXPECT_TRUE(builder_.Build(&err)); + EXPECT_EQ("", err); + EXPECT_EQ(1u, command_runner_.commands_ran_.size()); +} + TEST_F(BuildWithLogTest, RestatTest) { ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, "rule true\n" diff --git a/src/graph.cc b/src/graph.cc index 27013d577c..c90aaad2dc 100644 --- a/src/graph.cc +++ b/src/graph.cc @@ -193,7 +193,7 @@ bool DependencyScan::RecomputeOutputDirty(Edge* edge, EXPLAIN("command line changed for %s", output->path().c_str()); return true; } - if (entry->mtime < most_recent_input->mtime()) { + if (most_recent_input && entry->mtime < most_recent_input->mtime()) { // May also be dirty due to the mtime in the log being older than the // mtime of the most recent input. This can occur even when the mtime // on disk is newer if a previous run wrote to the output file but