Skip to content

[Crash] Segmentation Fault/Double Free in Multithreaded Access to Undefined YAML::Node via IsDefined() and reset() #1350

@Euoao

Description

@Euoao

Problem Description
When using yaml-cpp in multithreaded scenarios to check undefined nodes via IsDefined() and reset() methods, the program occasionally crashes with segmentation faults or double-free errors. The crash occurs even with read-only operations and no explicit node modifications.


Minimal Reproduction

#include <yaml-cpp/yaml.h>
#include <thread>
#include <vector>

YAML::Node rootNode(YAML::NodeType::Map);

YAML::Node foo() {
  YAML::Node node;
  node.reset(rootNode); 
  if (!node.IsDefined()) {
    return node;
  }
  node.reset(node["a"]);   // undefined
  if (!node.IsDefined()) {
    return node;
  }
  return node;
}

int main() {
  std::vector<std::thread> threads;
  for (int i = 0; i < 16; ++i) {
    threads.emplace_back(foo);
  }
  for (auto& t : threads) {
    t.join();
  }
}

Reproduction Script

#!/bin/bash
PROGRAM="./bazel-bin/src/main"
if [ ! -x "$PROGRAM" ]; then
    echo "Error: Program '$PROGRAM' not found or not executable."
    exit 1
fi
echo "Running $PROGRAM until crash occurs..."
count=0
while true; do
    count=$((count+1))
    $PROGRAM
    exit_code=$?
    if [ $exit_code -ne 0 ]; then
        echo "Program finished with exit code $exit_code"
        break
    fi
done
echo "Program crashed after $count runs"

Discovery Context
The crash manifests in real-world code resembling this pattern:

YAML::Node GetNode(std::string_view keyPath) {
  std::vector<std::string> keys = split(keyPath, ".");
  YAML::Node node;
  node.reset(rootNode);
  for (const auto& key : keys) {
    if (!node) break;
    node.reset(node[key]);
  }
  return node; 
}

This pattern is used extensively for configuration parsing. Despite being read-only and not modifying any nodes, concurrent access causes crashes.


Requests

  1. Is this a known thread-safety limitation of yaml-cpp's reference-counted nodes?
  2. What is the recommended pattern for concurrent read-only access to YAML configurations?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions