#!perl

# CVE-2026-13713 - CWE-416 (Use After Free) / CWE-415 (Double Free)
#
# In the bundled libsyck, when an anchor name is redefined or removed,
# syck_hdlr_remove_anchor / syck_hdlr_add_anchor freed the SyckNode that was
# stored under that name (syck_free_node). That node could still be live on
# the parser's value stack, so the grammar reached it again in
# syck_hdlr_add_node (handler.c:17) and freed the same node a second time.
#
# Trigger (7 bytes): YAML::Syck::Load("[&a\x01\n&a")
#
# This is the one defect of the four that faults WITHOUT AddressSanitizer:
# on a normal build the 48-byte node chunk is freed twice and the interpreter
# aborts (heap corruption -> SIGABRT/SIGTRAP). So against an unpatched libsyck
# this whole test file crashes and the harness reports it as failed
# ("Dubious, test returned ... wstat ..."). Once patched, Load() raises an
# ordinary parse error (caught below) and the file passes cleanly.

use strict;
use warnings;
use Test::More tests => 1;
use YAML::Syck ();

# The unpatched behaviour is a C-level abort() that eval cannot catch: it takes
# the whole file down before the assertion below and the harness reports the
# file as failed. Patched, Load() croaks on the malformed input, so we assert
# it died with the expected parse error (verifying the graceful failure, not
# merely that the process survived).
eval { YAML::Syck::Load("[&a\x01\n&a") };

like( $@, qr/syntax error/,
    'CVE-2026-13713: Load("[&a\\x01\\n&a") croaked with a parse error, not a double-free crash' );
