yeptris 0.6.31.2-arm-linux-eabihf → 0.6.33.1-arm-linux-eabihf
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/yeptris/3.4/native.so +0 -0
- data/lib/yeptris/node.rb +12 -3
- data/lib/yeptris/psych/visitors.rb +1 -1
- data/lib/yeptris/yaml.rb +1 -1
- data/lib/yeptris.rb +1 -1
- data/libyeptris.so +0 -0
- data/vendor/libyeptris/CMakeLists.txt +17 -5
- data/vendor/libyeptris/src/yeptris/dom/dom.c +52 -2
- data/vendor/libyeptris/src/yeptris/dom/ytape.c +273 -18
- data/vendor/libyeptris/src/yeptris/emit/emit.c +22 -1
- data/vendor/libyeptris/src/yeptris/emit/style.c +13 -1
- data/vendor/libyeptris/src/yeptris/emit/writer.c +433 -50
- data/vendor/libyeptris/src/yeptris/emit/writer.h +7 -0
- data/vendor/libyeptris/src/yeptris/events/values.c +83 -44
- data/vendor/libyeptris/src/yeptris/parse/engine.c +1189 -127
- data/vendor/libyeptris/src/yeptris/parse/engine.h +3 -0
- data/vendor/libyeptris/src/yeptris/parse/numbers.c +28 -3
- data/vendor/libyeptris/src/yeptris/parse/scalars.h +12 -0
- data/vendor/libyeptris/src/yeptris/parse.c +12 -4
- data/vendor/libyeptris/src/yeptris/scan/scan.c +42 -0
- data/vendor/libyeptris/src/yeptris/scan/scan.h +7 -0
- data/vendor/libyeptris/src/yeptris/tape.c +88 -1
- data/vendor/libyeptris/src/yeptris/tape_in.h +2 -0
- metadata +1 -1
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
#include "dom/dom.h"
|
|
21
21
|
#include "memory/allocator.h"
|
|
22
22
|
#include "memory/pool.h"
|
|
23
|
+
#include "parse/scalars.h"
|
|
23
24
|
#include "resolve/resolver.h"
|
|
24
25
|
#include "scan/json.h"
|
|
25
26
|
#include "scan/scan.h"
|
|
@@ -355,6 +356,14 @@ static uint32_t yt_flow_scan(const yeptris_json_tape* s, int* long_key) {
|
|
|
355
356
|
return 0xFFFFu; /* deeper than the scratch stack: the
|
|
356
357
|
* general kernel's depth path decides */
|
|
357
358
|
}
|
|
359
|
+
/* the container consumes the parent frame's pending slot
|
|
360
|
+
* (key or value); after it closes the OTHER slot is next —
|
|
361
|
+
* a container value left key_next pinned at 1, and every
|
|
362
|
+
* key after a container value skipped the law (the
|
|
363
|
+
* nightly's round-108 shape: {"": [...], "giant": x}) */
|
|
364
|
+
if (d > 0 && st[d].map) {
|
|
365
|
+
st[d].key_next = (uint8_t)!st[d].key_next;
|
|
366
|
+
}
|
|
358
367
|
d++;
|
|
359
368
|
if ((uint32_t)d > maxd) {
|
|
360
369
|
maxd = (uint32_t)d;
|
|
@@ -371,7 +380,12 @@ static uint32_t yt_flow_scan(const yeptris_json_tape* s, int* long_key) {
|
|
|
371
380
|
}
|
|
372
381
|
if (st[d].map && st[d].key_next == 0) {
|
|
373
382
|
uint32_t mlen = (uint32_t)(r >> 8) & 0xFFFFFFu;
|
|
374
|
-
if (kind == YEP_T_STR && mlen + 2u > 1024u
|
|
383
|
+
if (kind == YEP_T_STR && mlen + 2u > 1024u &&
|
|
384
|
+
yep_simple_key_chars((const char*)s->_src + (size_t)((uint32_t)(r >> 32)), mlen) +
|
|
385
|
+
2 >
|
|
386
|
+
1024) {
|
|
387
|
+
/* the budget counts characters (the round-108 shrink:
|
|
388
|
+
* a 2-byte code point at byte delta 1025 is legal) */
|
|
375
389
|
*long_key = 1;
|
|
376
390
|
}
|
|
377
391
|
st[d].key_next = 1;
|
|
@@ -429,7 +443,9 @@ static int yt_flow_classify_record(yep_ytape* t, const char* p, size_t open, siz
|
|
|
429
443
|
yep_json_walk w;
|
|
430
444
|
yep_json_tok tok;
|
|
431
445
|
yep_json_walk_init(&w, p, len, open, max_depth);
|
|
432
|
-
w.strict =
|
|
446
|
+
w.strict = 1; /* mirrors the engine pass-1 / dom builder gates:
|
|
447
|
+
* reject anything non-JSON so the span falls to
|
|
448
|
+
* the general kernel (whole/chunked agreement) */
|
|
433
449
|
int exhausted = 0;
|
|
434
450
|
for (;;) {
|
|
435
451
|
if (w.i - open > 256) {
|
|
@@ -1118,10 +1134,21 @@ static size_t yt_flat_run(yep_ytape* t, const char* p, size_t pos, size_t len, u
|
|
|
1118
1134
|
if (col + 1 != run_cc) {
|
|
1119
1135
|
return pos; /* off-column: the pop/nest logic owns it */
|
|
1120
1136
|
}
|
|
1137
|
+
/* document markers are the engine's alone — the "..."+content
|
|
1138
|
+
* error law lives there (the nightly's marshal crasher) */
|
|
1139
|
+
if (le - li >= 3 && (memcmp(p + li, "...", 3) == 0 || memcmp(p + li, "---", 3) == 0)) {
|
|
1140
|
+
size_t mk2 = li + 3;
|
|
1141
|
+
if (mk2 >= le || p[mk2] == ' ' || p[mk2] == '\t') {
|
|
1142
|
+
return pos;
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1121
1145
|
unsigned char c = (unsigned char)p[li];
|
|
1122
1146
|
if (c == '\t' || c == '-' || c == '&' || c == '!' || c == '*' || c == '\'' || c == '"' ||
|
|
1123
|
-
c == '[' || c == '{' || c == '|' || c == '>' || c == '%' || c == '?'
|
|
1124
|
-
|
|
1147
|
+
c == '[' || c == '{' || c == '|' || c == '>' || c == '%' || c == '?' ||
|
|
1148
|
+
!yep_plain_first_ok(c)) {
|
|
1149
|
+
return pos; /* indicators, tab-led, and the plain-first law
|
|
1150
|
+
(a ']' key rode the flat-run — the nightly's
|
|
1151
|
+
marshal crasher "<: .ba\n]ge: 21"): full arms */
|
|
1125
1152
|
}
|
|
1126
1153
|
if (!stop_set || p[ls] != ':' || (ls + 1 < le && p[ls + 1] != ' ' && p[ls + 1] != '\t')) {
|
|
1127
1154
|
return pos; /* not a plain key: value line */
|
|
@@ -1184,6 +1211,11 @@ static size_t yt_flat_run(yep_ytape* t, const char* p, size_t pos, size_t len, u
|
|
|
1184
1211
|
(vt + 1 >= le || p[vt + 1] == ' ' || p[vt + 1] == '\t' || p[vt + 1] == '#'))) {
|
|
1185
1212
|
return pos; /* block/flow/anchor values: the full arms */
|
|
1186
1213
|
}
|
|
1214
|
+
if (!yep_plain_first_ok(vc)) {
|
|
1215
|
+
return pos; /* ']' '}' ',' '@' '`': no plain value can start
|
|
1216
|
+
* there (the nightly's "k1: --a &p{\n0: ]" marshal
|
|
1217
|
+
* crasher) — the engine errors cleanly */
|
|
1218
|
+
}
|
|
1187
1219
|
/* a terminating ':' inside the value is the mapping-values error */
|
|
1188
1220
|
{
|
|
1189
1221
|
const char* h = (const char*)memchr(p + vt, ':', le - vt);
|
|
@@ -1225,6 +1257,15 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1225
1257
|
st[0].started = 1; /* the root's start event defers to its first pair */
|
|
1226
1258
|
int root_open = 0;
|
|
1227
1259
|
int root_evented = 0;
|
|
1260
|
+
uint32_t root_pair_col = 0; /* the root map's first pair line's column
|
|
1261
|
+
* (0 = none seen): the second-root dedent
|
|
1262
|
+
* law reads this, NOT content_col — the
|
|
1263
|
+
* pending arm never set content_col (" k:
|
|
1264
|
+
* &a", the nightly's run 39064966578,
|
|
1265
|
+
* issue #630) and arming content_col here
|
|
1266
|
+
* instead broke the " k: \n j: w" siblings
|
|
1267
|
+
* (the next nightly's crash-753ce4c1: the
|
|
1268
|
+
* map dissolved into four root scalars) */
|
|
1228
1269
|
(void)yt_put(t, ((uint64_t)YTP_EV_COMPACT << 56) | 1u);
|
|
1229
1270
|
(void)yt_put(t, ((uint64_t)YTP_EV_COMPACT << 56) | 3u);
|
|
1230
1271
|
size_t pos = 0;
|
|
@@ -1293,6 +1334,8 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1293
1334
|
if (n1 == ' ' || n1 == '\t') {
|
|
1294
1335
|
dash = 1;
|
|
1295
1336
|
}
|
|
1337
|
+
} else if (c == '-' && line_indent + 1 >= line_end) {
|
|
1338
|
+
dash = 1; /* a line-end dash is an indicator, not the scalar "-" */
|
|
1296
1339
|
}
|
|
1297
1340
|
size_t next = line_end < len ? (size_t)line_end + 1 : len;
|
|
1298
1341
|
if (!blank && !comment) {
|
|
@@ -1301,6 +1344,18 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1301
1344
|
if (c == '\t') {
|
|
1302
1345
|
return 1; /* tab-led content: the engine's error */
|
|
1303
1346
|
}
|
|
1347
|
+
/* document markers are the engine's alone: only it carries
|
|
1348
|
+
* the "..."+content error law (the nightly's marshal
|
|
1349
|
+
* crasher, "a: b\n... vi an : }" — the runner swallowed
|
|
1350
|
+
* the post-'...' content as a pair) */
|
|
1351
|
+
if (col == 0 && line_end - line_indent >= 3 &&
|
|
1352
|
+
(memcmp(p + line_indent, "...", 3) == 0 ||
|
|
1353
|
+
memcmp(p + line_indent, "---", 3) == 0)) {
|
|
1354
|
+
size_t mk = line_indent + 3;
|
|
1355
|
+
if (mk >= line_end || p[mk] == ' ' || p[mk] == '\t') {
|
|
1356
|
+
return 1;
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1304
1359
|
if (dash && depth > 0 && st[depth].pending && col >= st[depth].indent) {
|
|
1305
1360
|
/* the pending key resolves into a sequence: its own
|
|
1306
1361
|
* frame (the key's map survives below it) */
|
|
@@ -1340,6 +1395,28 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1340
1395
|
} else {
|
|
1341
1396
|
uint8_t of = yt_f_open_form(&st[depth - 1], depth == 1, st[depth].indent);
|
|
1342
1397
|
yt_f_open(F, &st[depth], of);
|
|
1398
|
+
if (depth == 1 && st[0].content_col == 0) {
|
|
1399
|
+
/* the root bookkeeping the anchored branch carries:
|
|
1400
|
+
* without it a dedent past the root map's column
|
|
1401
|
+
* pops to a content_col-0 st[0] and the pair arm
|
|
1402
|
+
* read "root pairs at column 0" — the nightly's
|
|
1403
|
+
* run 38128905644, " american:\n - Boston...\n
|
|
1404
|
+
* national:" split into PHANTOM DOCUMENTS
|
|
1405
|
+
* ("---\nb\n---\nv") while the engine rejected */
|
|
1406
|
+
st[0].content_col = st[depth].indent + 1;
|
|
1407
|
+
}
|
|
1408
|
+
if (st[depth].content_col == 0) {
|
|
1409
|
+
/* the opened map's pairs live at the KEY's
|
|
1410
|
+
* column (the anchored branch tracks this;
|
|
1411
|
+
* without it the off-column guard never fires
|
|
1412
|
+
* and a key line BETWEEN the resolved seq's
|
|
1413
|
+
* column and the parent's fell through to a
|
|
1414
|
+
* SILENTLY TRUNCATED document — the nightly's
|
|
1415
|
+
* run 38118641722, "ue:\n - one\n woc:\n
|
|
1416
|
+
* - one\n wt o- : thrt" dropped lines 3-5
|
|
1417
|
+
* while the engine rejected at 3:2) */
|
|
1418
|
+
st[depth].content_col = st[depth].indent + 1;
|
|
1419
|
+
}
|
|
1343
1420
|
root_open = 1;
|
|
1344
1421
|
st[depth].pending = 0;
|
|
1345
1422
|
}
|
|
@@ -1358,6 +1435,22 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1358
1435
|
while (depth > 0 && (st[depth].kind == 1 ? (col < st[depth].indent ||
|
|
1359
1436
|
(col <= st[depth].indent && !dash))
|
|
1360
1437
|
: col < st[depth].indent)) {
|
|
1438
|
+
if (st[depth].kind == 1 && col == st[depth].indent && !dash &&
|
|
1439
|
+
!(depth > 1 && st[depth - 1].kind == 0 &&
|
|
1440
|
+
st[depth - 1].indent == st[depth].indent)) {
|
|
1441
|
+
return 1; /* a non-dash line at an INDENTED seq's
|
|
1442
|
+
* column: the seq owns its column, the
|
|
1443
|
+
* pair cannot join it and cannot close
|
|
1444
|
+
* it (libyaml: "did not find expected
|
|
1445
|
+
* '-' indicator"; the nightly's run
|
|
1446
|
+
* 38117287882, "amer:\n - j\n n:\n
|
|
1447
|
+
* - Bksl,} -- }" — the runner popped
|
|
1448
|
+
* the seq and SILENTLY DROPPED the
|
|
1449
|
+
* lines while the engine rejected).
|
|
1450
|
+
* Only the INDENTLESS seq — parent map
|
|
1451
|
+
* keys at the same column — closes on
|
|
1452
|
+
* a key line there ("k:\n- j\nn: v") */
|
|
1453
|
+
}
|
|
1361
1454
|
if (st[depth].pending) {
|
|
1362
1455
|
return 1; /* empty "key:" mid-doc: the engine owns it */
|
|
1363
1456
|
}
|
|
@@ -1391,8 +1484,19 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1391
1484
|
vc == '?') {
|
|
1392
1485
|
return 1;
|
|
1393
1486
|
}
|
|
1394
|
-
if (vc
|
|
1395
|
-
return 1; /*
|
|
1487
|
+
if (!yep_plain_first_ok(vc)) {
|
|
1488
|
+
return 1; /* ']'/','/'}'/'@'/'`' first: no plain
|
|
1489
|
+
item can start there (the nightly's
|
|
1490
|
+
marshal crasher, "x:\n- ]\"#") — the
|
|
1491
|
+
engine errors cleanly */
|
|
1492
|
+
}
|
|
1493
|
+
if (vc == '-' && (vt + 1 >= line_end || p[vt + 1] == ' ' || p[vt + 1] == '\t' ||
|
|
1494
|
+
p[vt + 1] == '#')) {
|
|
1495
|
+
return 1; /* nested dash (incl. line-end — the
|
|
1496
|
+
nightly's "n:\n- -\t" crasher: a
|
|
1497
|
+
trailing bare '-' is an indicator,
|
|
1498
|
+
never the plain scalar "-"): the
|
|
1499
|
+
engine's nested seq */
|
|
1396
1500
|
}
|
|
1397
1501
|
/* compact map item "- k: v"? */
|
|
1398
1502
|
for (size_t ic = vt; ic < vend; ic++) {
|
|
@@ -1424,6 +1528,40 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1424
1528
|
!(c == '&' || c == '!' || c == '*' || c == '\'' || c == '"' || c == '[' ||
|
|
1425
1529
|
c == '{' || c == '|' || c == '>' || c == '%' || c == '?' || c == '-') &&
|
|
1426
1530
|
yep_plain_first_ok((unsigned char)c)) {
|
|
1531
|
+
if (depth == 0) {
|
|
1532
|
+
if (root_pair_col != 0 && col < root_pair_col) {
|
|
1533
|
+
/* a dedent below the root map's own pair column:
|
|
1534
|
+
* a SECOND root without "---" (issue #630, " k:
|
|
1535
|
+
* &a\n - r\na: b" — the pending-value root arm
|
|
1536
|
+
* never arms content_col, so the off-column
|
|
1537
|
+
* guard below cannot see this; the engine and
|
|
1538
|
+
* libyaml reject with "did not find expected
|
|
1539
|
+
* <document start>") */
|
|
1540
|
+
return 1;
|
|
1541
|
+
}
|
|
1542
|
+
if (root_pair_col == 0) {
|
|
1543
|
+
root_pair_col = col; /* the first root pair owns its column */
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
if (st[depth].kind == 0 &&
|
|
1547
|
+
((st[depth].content_col != 0 && col + 1 != st[depth].content_col &&
|
|
1548
|
+
(col != st[depth].indent || (depth == 0 && st[0].content_col > 1))) ||
|
|
1549
|
+
(st[depth].content_col == 0 && depth > 0 && !st[depth].pending &&
|
|
1550
|
+
col != st[depth].indent))) {
|
|
1551
|
+
/* an OFF-COLUMN pair. No pending key awaits it, so a
|
|
1552
|
+
* more-indented line cannot open a child and a
|
|
1553
|
+
* dedented one is a second root (the catch-39 law;
|
|
1554
|
+
* libyaml: "mapping values are not allowed in this
|
|
1555
|
+
* context"). Two states: a frame with its own content
|
|
1556
|
+
* column rejects every other column; a frame whose
|
|
1557
|
+
* content map already closed (the phantom close above)
|
|
1558
|
+
* only accepts pairs at its own key column. The pop
|
|
1559
|
+
* loop pops on col < indent alone — without these
|
|
1560
|
+
* checks "a:\n b: 1\nc: 2\n d: 3" rode the stale
|
|
1561
|
+
* frame as a phantom sibling (the nightly's run
|
|
1562
|
+
* 38179552341) */
|
|
1563
|
+
return 1;
|
|
1564
|
+
}
|
|
1427
1565
|
uint32_t kend = line_stop;
|
|
1428
1566
|
while (kend > t0 && (p[kend - 1] == ' ' || p[kend - 1] == '\t')) {
|
|
1429
1567
|
kend--;
|
|
@@ -1455,6 +1593,12 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1455
1593
|
return 1; /* an anchor needs a name (libyaml):
|
|
1456
1594
|
the engine owns the error */
|
|
1457
1595
|
}
|
|
1596
|
+
if (ne < line_end && p[ne] == '#') {
|
|
1597
|
+
return 1; /* a glued '#' is junk on the name
|
|
1598
|
+
(libyaml: "did not find expected
|
|
1599
|
+
alphabetic or numeric character") —
|
|
1600
|
+
the engine owns it */
|
|
1601
|
+
}
|
|
1458
1602
|
F->anchor_seq++;
|
|
1459
1603
|
aid = F->anchor_seq;
|
|
1460
1604
|
if (!yt_anchor_table(F)) {
|
|
@@ -1471,8 +1615,24 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1471
1615
|
* (aid rides it: an anchored container resolves through
|
|
1472
1616
|
* the S2900 + anchored-start form, not on_block_open) */
|
|
1473
1617
|
if (st[depth].kind == 0 && st[depth].content_col != 0 &&
|
|
1474
|
-
col + 1 != st[depth].content_col &&
|
|
1475
|
-
|
|
1618
|
+
col + 1 != st[depth].content_col &&
|
|
1619
|
+
(col != st[depth].indent || (depth == 0 && st[0].content_col > 1))) {
|
|
1620
|
+
return 1; /* off-column: a continuation line — the multiline arm;
|
|
1621
|
+
* at the ROOT the indent exemption dies once pairs
|
|
1622
|
+
* live above column 0: a col-0 line under a col-1
|
|
1623
|
+
* root is a DEDENT — a second root without "---",
|
|
1624
|
+
* the engine's error (libyaml: "did not find
|
|
1625
|
+
* expected <document start>") */
|
|
1626
|
+
}
|
|
1627
|
+
if (st[depth].kind != 0) {
|
|
1628
|
+
return 1; /* a pending "key:" over a SEQ frame: the
|
|
1629
|
+
* key cannot join the sequence (libyaml
|
|
1630
|
+
* "mapping values are not allowed in
|
|
1631
|
+
* this context"; the nightly's run
|
|
1632
|
+
* 38127584324, "k:\n- 42\n bar:\n
|
|
1633
|
+
* - 45 e." — the pending pushed UNDER
|
|
1634
|
+
* the seq and materialized as an ITEM
|
|
1635
|
+
* while the engine rejected) */
|
|
1476
1636
|
}
|
|
1477
1637
|
if (st[depth].kind == 0 && st[depth].content_col != 0 &&
|
|
1478
1638
|
col + 1 != st[depth].content_col && st[depth].phantom) {
|
|
@@ -1480,10 +1640,13 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1480
1640
|
st[depth].phantom = 0;
|
|
1481
1641
|
}
|
|
1482
1642
|
if (depth > 0 && st[depth].pending) {
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1643
|
+
/* chained same-column pending ("a:\na:"): resolving
|
|
1644
|
+
* the first via yt_f_open corrupts the frame mapping
|
|
1645
|
+
* when the second's container carries valued pairs —
|
|
1646
|
+
* the OPEN'd map swallows the second key as the
|
|
1647
|
+
* first pair's value (the nightly's run 38110714729
|
|
1648
|
+
* tree corruption). The engine owns the shape */
|
|
1649
|
+
return 1;
|
|
1487
1650
|
}
|
|
1488
1651
|
/* a spent key-SCALAR frame (resolved, phantom closed,
|
|
1489
1652
|
* no map of its own) gives its slot to the sibling —
|
|
@@ -1507,10 +1670,22 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1507
1670
|
st[depth].anchored_first = (uint8_t)(aid != 0);
|
|
1508
1671
|
} else {
|
|
1509
1672
|
if (st[depth].kind == 0 && st[depth].content_col != 0 &&
|
|
1510
|
-
col + 1 != st[depth].content_col &&
|
|
1511
|
-
|
|
1673
|
+
col + 1 != st[depth].content_col &&
|
|
1674
|
+
(col != st[depth].indent || (depth == 0 && st[0].content_col > 1))) {
|
|
1675
|
+
return 1; /* off-column: a continuation line — the multiline arm;
|
|
1676
|
+
* the root's indent exemption dies once pairs
|
|
1677
|
+
* live above column 0 (dedent = second root) */
|
|
1512
1678
|
}
|
|
1513
1679
|
if (depth > 0 && st[depth].pending && st[depth].aid != 0) {
|
|
1680
|
+
if (depth > 1) {
|
|
1681
|
+
/* an anchored pending BELOW the root frame: the
|
|
1682
|
+
* deferral's records only flush at depth 1 — a
|
|
1683
|
+
* deeper one drops its pairs at EOF ("4:\n4: r\n
|
|
1684
|
+
* 5:\n &5\n 5: e" lost the anchored map; the
|
|
1685
|
+
* nightly's run 38202382251) — the engine
|
|
1686
|
+
* resolves it */
|
|
1687
|
+
return 1;
|
|
1688
|
+
}
|
|
1514
1689
|
if (col <= st[depth].indent) {
|
|
1515
1690
|
return 1; /* same-column "content": the anchored value is
|
|
1516
1691
|
* null and this line is a sibling — the engine */
|
|
@@ -1555,6 +1730,14 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1555
1730
|
} else if (depth > 0 && st[depth].pending) {
|
|
1556
1731
|
uint8_t of = yt_f_open_form(&st[depth - 1], depth == 1, st[depth].indent);
|
|
1557
1732
|
yt_f_open(F, &st[depth], of);
|
|
1733
|
+
if (depth == 1 && st[0].content_col == 0) {
|
|
1734
|
+
/* the pending->MAP resolution needs the same
|
|
1735
|
+
* root bookkeeping the seq arm gained (run
|
|
1736
|
+
* 38134498534, " e:\n f: g\nh: i" — the
|
|
1737
|
+
* dedent popped to a content_col-0 root and
|
|
1738
|
+
* the doc accepted what the engine rejects) */
|
|
1739
|
+
st[0].content_col = st[depth].indent + 1;
|
|
1740
|
+
}
|
|
1558
1741
|
root_open = 1;
|
|
1559
1742
|
st[depth].pending = 0;
|
|
1560
1743
|
if (col == st[depth].indent) {
|
|
@@ -1578,6 +1761,10 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1578
1761
|
if (st[depth].phantom) {
|
|
1579
1762
|
yt_f_close(F, st[depth].kind);
|
|
1580
1763
|
st[depth].phantom = 0;
|
|
1764
|
+
st[depth].content_col = 0; /* the content map is
|
|
1765
|
+
* gone: its column must not
|
|
1766
|
+
* greet later pairs (the
|
|
1767
|
+
* stale frame below) */
|
|
1581
1768
|
}
|
|
1582
1769
|
} else {
|
|
1583
1770
|
yt_f_start(F, &st[depth]);
|
|
@@ -1600,6 +1787,29 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1600
1787
|
}
|
|
1601
1788
|
ne++;
|
|
1602
1789
|
}
|
|
1790
|
+
if (ne < line_end && p[ne] == '#') {
|
|
1791
|
+
return 1; /* a glued '#' is junk on the
|
|
1792
|
+
* name (the engine errors:
|
|
1793
|
+
* "did not find expected
|
|
1794
|
+
* alphabetic or numeric
|
|
1795
|
+
* character") */
|
|
1796
|
+
}
|
|
1797
|
+
{
|
|
1798
|
+
size_t ae = ne;
|
|
1799
|
+
while (ae < line_end && (p[ae] == ' ' || p[ae] == '\t')) {
|
|
1800
|
+
ae++;
|
|
1801
|
+
}
|
|
1802
|
+
if (ae < line_end && p[ae] != '#') {
|
|
1803
|
+
return 1; /* an alias node is COMPLETE —
|
|
1804
|
+
* on the line only a blank
|
|
1805
|
+
* then a comment may follow
|
|
1806
|
+
* ("<<: *x &y": the engine
|
|
1807
|
+
* errors, libyaml "did not
|
|
1808
|
+
* find expected key"; this
|
|
1809
|
+
* branch silently dropped the
|
|
1810
|
+
* bytes) */
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1603
1813
|
uint32_t taid = 0;
|
|
1604
1814
|
if (!yt_anchor_get(F, (uint32_t)(vt + 1), (uint32_t)(ne - vt - 1), &taid)) {
|
|
1605
1815
|
return 1; /* undefined alias: the engine errors */
|
|
@@ -1662,10 +1872,25 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1662
1872
|
}
|
|
1663
1873
|
if (vc == '|' && aid == 0 && !st[depth].anchored_first &&
|
|
1664
1874
|
(vt + 1 >= line_end || p[vt + 1] == ' ' || p[vt + 1] == '\t')) {
|
|
1875
|
+
/* the header tail: only blanks and an optional
|
|
1876
|
+
* comment may follow the indicator (libyaml:
|
|
1877
|
+
* "did not find expected comment or line break";
|
|
1878
|
+
* the nightly's run 38119775008, "ext: | c* " —
|
|
1879
|
+
* this arm took the literal and SILENTLY DROPPED
|
|
1880
|
+
* the trailing header bytes while the engine
|
|
1881
|
+
* rejected) */
|
|
1882
|
+
size_t ht = vt + 1;
|
|
1883
|
+
while (ht < line_end && (p[ht] == ' ' || p[ht] == '\t')) {
|
|
1884
|
+
ht++;
|
|
1885
|
+
}
|
|
1886
|
+
if (ht < line_end && p[ht] != '#') {
|
|
1887
|
+
return 1;
|
|
1888
|
+
}
|
|
1665
1889
|
/* bare literal block, clip chomp: measure the block,
|
|
1666
1890
|
* copy it into the finish pool, emit the pool form */
|
|
1667
1891
|
size_t scan = next;
|
|
1668
1892
|
uint32_t bindent = 0;
|
|
1893
|
+
uint32_t lead_blank_max = 0;
|
|
1669
1894
|
int have_bi = 0, have_content = 0;
|
|
1670
1895
|
size_t clen = 0, tb = 0;
|
|
1671
1896
|
size_t end_scan = scan;
|
|
@@ -1697,6 +1922,9 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1697
1922
|
/* a blank line: spaces past the block indent are
|
|
1698
1923
|
* CONTENT; only stripped-empty lines clip away */
|
|
1699
1924
|
size_t ind = ie - ls;
|
|
1925
|
+
if (!have_content && ind > lead_blank_max) {
|
|
1926
|
+
lead_blank_max = (uint32_t)ind;
|
|
1927
|
+
}
|
|
1700
1928
|
size_t res = have_bi && ind > bindent ? ind - bindent : 0;
|
|
1701
1929
|
clen += res + 1;
|
|
1702
1930
|
if (res == 0) {
|
|
@@ -1712,6 +1940,22 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1712
1940
|
if (ind <= col) {
|
|
1713
1941
|
break; /* dedented past the block */
|
|
1714
1942
|
}
|
|
1943
|
+
if (ind < lead_blank_max) {
|
|
1944
|
+
return 1; /* a LEADING blank line
|
|
1945
|
+
* with MORE indent
|
|
1946
|
+
* floors the block
|
|
1947
|
+
* (libyaml's
|
|
1948
|
+
* auto-detect takes
|
|
1949
|
+
* the blanks' max;
|
|
1950
|
+
* content below the
|
|
1951
|
+
* floor breaks the
|
|
1952
|
+
* map — Psych: "did
|
|
1953
|
+
* not find expected
|
|
1954
|
+
* key"; the nightly's
|
|
1955
|
+
* run 38163867815,
|
|
1956
|
+
* "a: |\n \n b"):
|
|
1957
|
+
* the engine's error */
|
|
1958
|
+
}
|
|
1715
1959
|
bindent = ind;
|
|
1716
1960
|
have_bi = 1;
|
|
1717
1961
|
} else if (ind < bindent) {
|
|
@@ -1735,7 +1979,9 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1735
1979
|
spilled = 1;
|
|
1736
1980
|
}
|
|
1737
1981
|
end_scan =
|
|
1738
|
-
(le < len && p[le] == '\r' && le + 1 < len
|
|
1982
|
+
(le < len && p[le] == '\r' && le + 1 < len && p[le + 1] == '\n')
|
|
1983
|
+
? le + 2
|
|
1984
|
+
: le + 1; /* lone CR is a 1-byte break */
|
|
1739
1985
|
scan = end_scan;
|
|
1740
1986
|
}
|
|
1741
1987
|
if (!have_content) {
|
|
@@ -1748,7 +1994,14 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1748
1994
|
return 1;
|
|
1749
1995
|
}
|
|
1750
1996
|
}
|
|
1751
|
-
|
|
1997
|
+
/* the BLOCK is clen-sized: both copy paths write
|
|
1998
|
+
* every measured line (the clip lives in the
|
|
1999
|
+
* SPAN, not the copy) — allocating flen wrote
|
|
2000
|
+
* tb bytes past the block whenever a literal
|
|
2001
|
+
* ended with stripped-empty lines (the nightly's
|
|
2002
|
+
* run 38137087116 ASan heap-buffer-overflow,
|
|
2003
|
+
* WRITE at ytape.c's re-walk memcpy) */
|
|
2004
|
+
char* dst = (char*)yep_pool_alloc(F->pool, clen, 16);
|
|
1752
2005
|
if (dst == NULL) {
|
|
1753
2006
|
return 1;
|
|
1754
2007
|
}
|
|
@@ -1795,8 +2048,10 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1795
2048
|
q += le - (ls + bindent);
|
|
1796
2049
|
*q++ = '\n';
|
|
1797
2050
|
}
|
|
1798
|
-
s2 = (le < len && p[le] == '\r' && le + 1 < len
|
|
1799
|
-
|
|
2051
|
+
s2 = (le < len && p[le] == '\r' && le + 1 < len &&
|
|
2052
|
+
p[le + 1] == '\n')
|
|
2053
|
+
? le + 2
|
|
2054
|
+
: le + 1; /* lone CR is a 1-byte break */
|
|
1800
2055
|
}
|
|
1801
2056
|
}
|
|
1802
2057
|
if ((size_t)(q - dst) != clen) {
|
|
@@ -51,6 +51,9 @@ YEPTRIS_API size_t yeptris_serialize_into_ex(YeptrisDocument handle,
|
|
|
51
51
|
em.w.p = NULL;
|
|
52
52
|
em.w.last = 0;
|
|
53
53
|
em.w.force_flow = 0;
|
|
54
|
+
em.w.in_flow = 0;
|
|
55
|
+
em.w.flow_item = 0;
|
|
56
|
+
em.w.unserializable = 0;
|
|
54
57
|
em.w.canonical = opts_canonical(opts);
|
|
55
58
|
em.w.explicit_doc_start = opts_doc_marker(opts);
|
|
56
59
|
em.w.json = 0;
|
|
@@ -116,6 +119,9 @@ YEPTRIS_API char* yeptris_serialize_ex(YeptrisDocument handle, const yeptris_emi
|
|
|
116
119
|
em.w.p = NULL;
|
|
117
120
|
em.w.last = 0;
|
|
118
121
|
em.w.force_flow = 0;
|
|
122
|
+
em.w.in_flow = 0;
|
|
123
|
+
em.w.flow_item = 0;
|
|
124
|
+
em.w.unserializable = 0;
|
|
119
125
|
em.w.canonical = opts_canonical(opts);
|
|
120
126
|
em.w.explicit_doc_start = opts_doc_marker(opts);
|
|
121
127
|
em.w.json = 0;
|
|
@@ -160,7 +166,7 @@ YEPTRIS_API char* yeptris_serialize_ex(YeptrisDocument handle, const yeptris_emi
|
|
|
160
166
|
* any growth; every post-run touch goes through the writer's
|
|
161
167
|
* pointer (the first round's abort was exactly this aliasing) */
|
|
162
168
|
out = em.w.p;
|
|
163
|
-
if (em.w.oom) {
|
|
169
|
+
if (em.w.oom || em.w.unserializable) {
|
|
164
170
|
free(out);
|
|
165
171
|
if (em.canon_names.sys != NULL) {
|
|
166
172
|
yep_nametab_free(&em.canon_names);
|
|
@@ -200,6 +206,9 @@ YEPTRIS_API char* yeptris_serialize_json(YeptrisDocument handle, size_t* len) {
|
|
|
200
206
|
em.w.p = NULL;
|
|
201
207
|
em.w.last = 0;
|
|
202
208
|
em.w.force_flow = 0;
|
|
209
|
+
em.w.in_flow = 0;
|
|
210
|
+
em.w.flow_item = 0;
|
|
211
|
+
em.w.unserializable = 0;
|
|
203
212
|
em.w.canonical = 0;
|
|
204
213
|
em.w.explicit_doc_start = 0; /* JSON output carries no --- */
|
|
205
214
|
em.w.json = 1;
|
|
@@ -258,6 +267,9 @@ YEPTRIS_API char* yeptris_serialize_json_ex(YeptrisDocument handle, size_t* len,
|
|
|
258
267
|
em.w.p = NULL;
|
|
259
268
|
em.w.last = 0;
|
|
260
269
|
em.w.force_flow = 0;
|
|
270
|
+
em.w.in_flow = 0;
|
|
271
|
+
em.w.flow_item = 0;
|
|
272
|
+
em.w.unserializable = 0;
|
|
261
273
|
em.w.canonical = 0;
|
|
262
274
|
em.w.explicit_doc_start = 0; /* JSON output carries no --- */
|
|
263
275
|
em.w.json = 1;
|
|
@@ -310,6 +322,9 @@ char* yep_serialize_json_compact(const yeptris_document* doc, size_t* len) {
|
|
|
310
322
|
em.w.p = NULL;
|
|
311
323
|
em.w.last = 0;
|
|
312
324
|
em.w.force_flow = 0;
|
|
325
|
+
em.w.in_flow = 0;
|
|
326
|
+
em.w.flow_item = 0;
|
|
327
|
+
em.w.unserializable = 0;
|
|
313
328
|
em.w.canonical = 0;
|
|
314
329
|
em.w.explicit_doc_start = 0; /* JSON output carries no --- */
|
|
315
330
|
em.w.json = 1;
|
|
@@ -362,6 +377,9 @@ char* yep_serialize_json_pretty(const yeptris_document* doc, size_t* len) {
|
|
|
362
377
|
em.w.p = NULL;
|
|
363
378
|
em.w.last = 0;
|
|
364
379
|
em.w.force_flow = 0;
|
|
380
|
+
em.w.in_flow = 0;
|
|
381
|
+
em.w.flow_item = 0;
|
|
382
|
+
em.w.unserializable = 0;
|
|
365
383
|
em.w.canonical = 0;
|
|
366
384
|
em.w.explicit_doc_start = 0; /* JSON output carries no --- */
|
|
367
385
|
em.w.json = 1;
|
|
@@ -430,6 +448,9 @@ YEPTRIS_API size_t yeptris_serialize_stream(YeptrisDocument handle,
|
|
|
430
448
|
em.w.p = NULL;
|
|
431
449
|
em.w.last = 0;
|
|
432
450
|
em.w.force_flow = 0;
|
|
451
|
+
em.w.in_flow = 0;
|
|
452
|
+
em.w.flow_item = 0;
|
|
453
|
+
em.w.unserializable = 0;
|
|
433
454
|
em.w.canonical = opts_canonical(opts);
|
|
434
455
|
em.w.explicit_doc_start = opts_doc_marker(opts);
|
|
435
456
|
em.w.json = 0;
|
|
@@ -19,6 +19,13 @@ int yep_style_plain_safe(const char* p, uint32_t len) {
|
|
|
19
19
|
if (is_blank(p[0]) || is_blank(p[len - 1])) {
|
|
20
20
|
return 0;
|
|
21
21
|
}
|
|
22
|
+
if (len >= 3 && (unsigned char)p[0] == 0xef && (unsigned char)p[1] == 0xbb &&
|
|
23
|
+
(unsigned char)p[2] == 0xbf) {
|
|
24
|
+
/* a LEADING U+FEFF re-parses as a document BOM and vanishes —
|
|
25
|
+
* the emitted form must carry its escape ("\uFEFF", the
|
|
26
|
+
* nightly's run 38258674337); mid-token BOMs ride plain */
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
22
29
|
switch (p[0]) {
|
|
23
30
|
case ':':
|
|
24
31
|
/* libyaml (Psych symbol dumps ":name"): a leading colon only
|
|
@@ -119,7 +126,12 @@ int yep_style_plain_safe(const char* p, uint32_t len) {
|
|
|
119
126
|
}
|
|
120
127
|
}
|
|
121
128
|
/* document markers */
|
|
122
|
-
if (
|
|
129
|
+
if (len >= 3 && (memcmp(p, "---", 3) == 0 || memcmp(p, "...", 3) == 0) &&
|
|
130
|
+
(len == 3 || p[3] == ' ' || p[3] == '\t' || p[3] == '\n' || p[3] == '\r')) {
|
|
131
|
+
/* a PREFIX marker is worse than the bare one: emitted plain at
|
|
132
|
+
* line start, "--- ..." re-reads as a document marker (the
|
|
133
|
+
* nightly's "--- --- >" folded-plain crasher) — libyaml quotes
|
|
134
|
+
* both */
|
|
123
135
|
return 0;
|
|
124
136
|
}
|
|
125
137
|
return 1;
|