Merge "Fix hwasan error for CAN HAL"
diff --git a/automotive/can/aidl/default/tools/configurator/canprototools.cpp b/automotive/can/aidl/default/tools/configurator/canprototools.cpp
index 2aea315..84edd94 100644
--- a/automotive/can/aidl/default/tools/configurator/canprototools.cpp
+++ b/automotive/can/aidl/default/tools/configurator/canprototools.cpp
@@ -51,15 +51,20 @@
     return std::string(buff, 0, std::min(n, got));
 }
 
-std::optional<CanBusConfig> parseConfigFile(const std::string& filepath) {
-    std::ifstream cfg_stream(filepath);
-
-    // text headers that would be present in a plaintext proto config file.
+/*
+  parseConfigFile *used to* contain the body of parseConfigStream. However, it seems there's some
+  sort of odd behavior with IstreamInputStream and/or TextFormat::Parse, which causes HW Address
+  Sanitizer to flag a "tag-mismatch" in this function. Having the ifstream defined in a wrapper
+  function seems to solve this problem. The exact cause of this problem is yet unknown, but probably
+  lies somewhere in the protobuf implementation.
+*/
+static __attribute__((noinline)) std::optional<CanBusConfig> parseConfigStream(
+        std::ifstream& cfg_stream) {
     static const std::array<std::string, 3> text_headers = {"buses", "#", "controller"};
     auto cfg_file_snippet = readString(cfg_stream, 10);
 
     if (!cfg_file_snippet.has_value()) {
-        LOG(ERROR) << "Can't open " << filepath << " for reading";
+        LOG(ERROR) << "Can't read config from stream (maybe failed to open file?)";
         return std::nullopt;
     }
     cfg_stream.seekg(0);
@@ -77,16 +82,25 @@
     if (text_format) {
         google::protobuf::io::IstreamInputStream pb_stream(&cfg_stream);
         if (!google::protobuf::TextFormat::Parse(&pb_stream, &config)) {
-            LOG(ERROR) << "Failed to parse (text format) " << filepath;
+            LOG(ERROR) << "Parsing text format config failed";
             return std::nullopt;
         }
     } else if (!config.ParseFromIstream(&cfg_stream)) {
-        LOG(ERROR) << "Failed to parse (binary format) " << filepath;
+        LOG(ERROR) << "Parsing binary format config failed";
         return std::nullopt;
     }
     return config;
 }
 
+std::optional<CanBusConfig> parseConfigFile(const std::string& filepath) {
+    std::ifstream cfg_stream(filepath);
+    auto cfg_maybe = parseConfigStream(cfg_stream);
+    if (!cfg_maybe.has_value()) {
+        LOG(ERROR) << "Failed to parse " << filepath;
+    }
+    return cfg_maybe;
+}
+
 std::optional<BusConfig> fromPbBus(const Bus& pb_bus) {
     BusConfig bus_cfg = {};
     bus_cfg.name = pb_bus.name();