Explicit `!!null` tag with empty content loads as a Scalar node instead of Null
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 82/100
Direzione di ricerca
Il bug si trova alla fine di SingleDocParser::HandleNode in src/singledocparser.cpp, dove il ramo tag == "?" emette OnNull e ogni altro tag ricade in OnScalar con un valore vuoto. Compila la libreria, poi esegui la riproduzione della issue (YAML::Load("---\ntest: !!null \nfoo: bar")) e verifica che doc["test"].IsNull() restituisca false. È completato quando questa verifica restituisce true, l'ancora continua a essere passata e i test esistenti continuano a passare, incluso quello per !!str su contenuto vuoto, che deve mantenere il comportamento attuale.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Location (jbeder/yaml-cpp @ default branch c5e6536):
src/singledocparser.cpp:149-152— end ofSingleDocParser::HandleNodefor a node with properties but no content
if (tag == "?")
eventHandler.OnNull(mark, anchor);
else
eventHandler.OnScalar(mark, tag, anchor, "");
Problem
YAML::Node doc = YAML::Load("---\ntest: !!null \nfoo: bar");
doc["test"].IsNull(); // false: Scalar node, value "", tag "tag:yaml.org,2002:null"
doc["foo"].as<std::string>(); // "bar" (rest of the document is fine)
For a node with properties but no content, HandleNode emits OnNull only when the tag is the non-specific "?". An explicit tag always goes to OnScalar(mark, tag, anchor, ""), including tag:yaml.org,2002:null.
Expected: doc["test"].IsNull() == true (Type() == YAML::NodeType::Null), the same as for test: with no tag. Here the node is explicitly tagged tag:yaml.org,2002:null (10.2.1.1 Null), and its content is empty, which the Core schema also resolves to null (/* Empty */ → tag:yaml.org,2002:null, 10.3.2). So it isn't an empty string like "" or !!str, and the input is valid.
Scope: only explicit !!null with empty content. No change is proposed to how other explicit tags on empty nodes (e.g. !!str → "") are handled, or to non-empty !!null content.
Reproduction
#include <iostream>
#include "yaml-cpp/yaml.h"
int main() {
YAML::Node doc = YAML::Load("---\ntest: !!null \nfoo: bar");
std::cout << std::boolalpha
<< "IsNull: " << doc["test"].IsNull() << "\n"
<< "IsScalar: " << doc["test"].IsScalar() << "\n"
<< "Tag: " << doc["test"].Tag() << "\n";
}
Observed (gtest on the commit above):
Value of: doc["test"].IsNull()
Actual: false
Expected: true
Environment:
- Commit:
c5e65360373d1d99d6b6848c991cd4fcee435009(master) - Toolchain: GCC 11.5.0
Already fixed in nodeca/js-yaml
js-yaml is another YAML implementation of the same spec; it fixed the same input. PR: https://github.com/nodeca/js-yaml/pull/155 — "error parsing named null" (merged 2014-12-18T21:08:19Z, merge commit cb5a2d8409e). Its null-type resolver now accepts an empty (no content) node, so test: !!null with empty content loads as null instead of failing; the added test uses the same document as above.
How js-yaml fixed it:
--- a/lib/js-yaml/type/null.js
+++ b/lib/js-yaml/type/null.js
@@ -3,6 +3,10 @@
var Type = require('../type');
function resolveYamlNull(data) {
+ if (null === data) {
+ return true;
+ }
+
var max = data.length;
return (max === 1 && data === '~') ||
--- a/test/issues/0155.js
+++ b/test/issues/0155.js
@@ -0,0 +1,10 @@
+'use strict';
+
+
+var assert = require('assert');
+var yaml = require('../../');
+
+
+test('Named null', function () {
+ assert.deepEqual(yaml.load('---\ntest: !!null \nfoo: bar'), { test: null, foo: 'bar' });
+});
Suggested fix
In HandleNode, emit OnNull for an empty node tagged tag:yaml.org,2002:null, as for the non-specific ? tag (the anchor is kept); other explicit tags on empty content are unchanged:
diff --git a/src/singledocparser.cpp b/src/singledocparser.cpp
--- a/src/singledocparser.cpp
+++ b/src/singledocparser.cpp
@@ -146,7 +146,7 @@ void SingleDocParser::HandleNode(EventHandler& eventHandler) {
break;
}
- if (tag == "?")
+ if (tag == "?" || tag == "tag:yaml.org,2002:null")
eventHandler.OnNull(mark, anchor);
else
eventHandler.OnScalar(mark, tag, anchor, "");
Verified on c5e6536 (GCC 11.4.0, bundled GoogleTest 1.16.0): the test above fails without this patch and passes with it; no other test results change.
I can submit a PR for this.
Related: #1290 (untagged empty value converts to the string "null"; about as<std::string>() on a Null node, while here the node is not Null), #1460 (closed; source text for plain null scalars) and #641 (open draft; general tag resolver design) do not report this case.
- Lingua principale
- C++
- Stelle
- 6.1k
- Fork
- 2.2k
- Merge medio
- 22h 2m
- PR unite (30g)
- 1
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di jbeder/yaml-cpp
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 62/100
-
Difficoltà 3/5 Mezza giornata Idoneità per principianti 55/100
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 62/100
-
Parser truncates trailing newlines in multiline quoted scalarsForse già presa @LucaCiucci l’ha presa 19 giorni fa. Aperta
Difficoltà 3/5 Mezza giornata Idoneità per principianti 15/100
Tutte le issue di jbeder/yaml-cpp
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 80/100
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 82/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
eclipse-score/lifecycle#929 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
colbymchenry/codegraph#3223 ·
I maintainer di solito rispondono entro 1 giorno