]> Cypherpunks repositories - keks.git/commitdiff
Unify size types and check overflows
authorSergey Matveev <stargrave@stargrave.org>
Wed, 16 Oct 2024 14:06:55 +0000 (17:06 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Wed, 16 Oct 2024 15:08:15 +0000 (18:08 +0300)
29 files changed:
cyac/cmd/cer-verify/cer-verify.c
cyac/cmd/lib/mmap.c
cyac/cmd/lib/printai.c [new file with mode: 0644]
cyac/cmd/lib/printai.h [new file with mode: 0644]
cyac/cmd/lib/printai.o.do [new file with mode: 0644]
cyac/cmd/print-items/print-items.c
cyac/cmd/print-items/print-items.do
cyac/cmd/print-itered/print-itered.c
cyac/cmd/print-itered/print-itered.do
cyac/cmd/test-vector/test-vector.c
cyac/lib/dec.c
cyac/lib/dec.h
cyac/lib/dectai.c
cyac/lib/dectai.h
cyac/lib/enc.c
cyac/lib/enc.h
cyac/lib/enctai.c
cyac/lib/enctai.h
cyac/lib/err.c
cyac/lib/err.h
cyac/lib/items.c
cyac/lib/items.h
cyac/lib/iter.c
cyac/lib/iter.h
cyac/lib/pki/cer.c
cyac/lib/pki/cer.h
cyac/lint/.clang-format [new file with mode: 0644]
cyac/lint/iwyu-maps.imp [new file with mode: 0644]
gyac/dec.go

index 8c4018d68b70cb43b483fa60fc56fe953cafffc870a0a3f8b6a53ba15675bc15..07ac5d0e8583f1777ce86275fb961a3ac2d3fdf07226a26f4710a49ec04dcd73 100644 (file)
 
 #include <assert.h>
 #include <errno.h>
-#include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/time.h>
+#include <time.h>
 
 #include <yac/err.h>
+#include <yac/items.h>
 #include <yac/pki/cer.h>
 
 #include "../lib/mmap.h"
@@ -36,20 +36,19 @@ main(int argc, char **argv)
         fprintf(stderr, "Usage: %s EE.cer [CA.cer ...]\n", argv[0]);
         return EXIT_FAILURE;
     }
-    const ptrdiff_t cersLen = (ptrdiff_t)argc - 1;
-    struct YACCer *cers = calloc((size_t)cersLen, sizeof(struct YACCer));
+    const size_t cersLen = (size_t)argc - 1;
+    struct YACCer *cers = calloc(cersLen, sizeof(struct YACCer));
     assert(cers != NULL);
     char *failReason = NULL;
     for (int i = 1; i < argc; i++) {
         unsigned char *buf = NULL;
         size_t len = 0;
         if (!Mmap(&buf, &len, argv[i])) {
-            fprintf(stderr, "%s\n", strerror(errno));
             exit(EXIT_FAILURE);
         }
         fputs(argv[i], stdout);
         fputs(":\t", stdout);
-        ptrdiff_t off = 0;
+        size_t off = 0;
         enum YACErr err = YACCerParse(&(cers[i - 1]), &off, &failReason, buf, len);
         if (err != YACErrNo) {
             fprintf(stderr, "%s\n", failReason);
@@ -64,8 +63,9 @@ main(int argc, char **argv)
         fputs("\n", stdout);
     }
 
-    struct timeval now;
-    if (gettimeofday(&now, NULL) != 0) {
+    struct timespec now;
+    errno = 0;
+    if (clock_gettime(CLOCK_REALTIME, &now) != 0) {
         fprintf(stderr, "%s\n", strerror(errno));
         return EXIT_FAILURE;
     }
@@ -94,8 +94,8 @@ main(int argc, char **argv)
             break;
         }
         {
-            ptrdiff_t ku = YACItemsGetByKey(&(verifier->items), verifier->load, "ku");
-            if ((ku == -1) || YACItemsGetByKey(&(verifier->items), ku, "ca") == -1) {
+            size_t ku = YACItemsGetByKey(&(verifier->items), verifier->load, "ku");
+            if ((ku == 0) || YACItemsGetByKey(&(verifier->items), ku, "ca") == 0) {
                 fputs("no ca ku\n", stdout);
                 return EXIT_FAILURE;
             }
index 9a0c8cecf82137fd17bbe828d8cd54e4cea2c43c5ea0e869d7cadfeb698edc3d..45f4b93054fac2d6260e0dbb4b3f6b4aadb51de89ca497fe5b28ce88e7294bc3 100644 (file)
@@ -1,3 +1,4 @@
+#include <errno.h>
 #include <fcntl.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -21,6 +22,11 @@ Mmap(unsigned char **buf, size_t *len, const char *path)
         return false;
     }
     (*len) = (size_t)sb.st_size;
+    errno = 0;
     (*buf) = mmap(NULL, *len, PROT_READ, MAP_SHARED, fd, 0);
+    if ((*buf) == MAP_FAILED) {
+        fprintf(stderr, "mmap: %s\n", strerror(errno));
+        return false;
+    }
     return true;
 }
diff --git a/cyac/cmd/lib/printai.c b/cyac/cmd/lib/printai.c
new file mode 100644 (file)
index 0000000..f762889
--- /dev/null
@@ -0,0 +1,64 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <yac/dectai.h>
+#include <yac/err.h>
+
+#include "hex.h"
+#include "printai.h"
+
+enum YACErr
+PrintTAI64(const unsigned char *buf, const size_t len)
+{
+    char *hex = NULL;
+    if (len == 16) {
+        hex = HexEnc(buf, len);
+        fprintf(stdout, "TAI64NA(%s)\n", hex);
+        free(hex);
+        return YACErrNo;
+    }
+    switch (len) {
+    case 8:
+        fputs("TAI64(", stdout);
+        break;
+    case 12:
+        fputs("TAI64N(", stdout);
+        break;
+    }
+    struct timespec tv;
+    enum YACErr err = YACTAI64ToTimespec(&tv, buf, len);
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wswitch-enum"
+    switch (err) {
+#pragma clang diagnostic pop
+    case YACErrNo:
+        break;
+    case YACErrTAI64InPast:
+        hex = HexEnc(buf, len);
+        fprintf(stdout, "in past: %s)\n", hex);
+        free(hex);
+        return YACErrNo;
+    default:
+        return err;
+    }
+    time_t t = tv.tv_sec;
+    struct tm *tm = localtime(&t);
+    if (tm == NULL) {
+        hex = HexEnc(buf, len);
+        fprintf(stdout, "unrepresentable: %s)\n", hex);
+        free(hex);
+        return YACErrNo;
+    }
+    {
+        char human[20] = {0};
+        strftime(human, sizeof human, "%Y-%m-%d %H:%M:%S", tm);
+        fputs(human, stdout);
+    }
+    if (len == 12) {
+        fprintf(stdout, ".%09zu", tv.tv_nsec);
+    }
+    fputs(")\n", stdout);
+    return YACErrNo;
+}
diff --git a/cyac/cmd/lib/printai.h b/cyac/cmd/lib/printai.h
new file mode 100644 (file)
index 0000000..c408b4d
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef YAC_PRINTAI_H
+#define YAC_PRINTAI_H
+
+#include <stddef.h>
+
+#include <yac/err.h>
+
+enum YACErr
+PrintTAI64(const unsigned char *buf, const size_t len);
+
+#endif // YAC_PRINTAI_H
diff --git a/cyac/cmd/lib/printai.o.do b/cyac/cmd/lib/printai.o.do
new file mode 100644 (file)
index 0000000..4d571c2
--- /dev/null
@@ -0,0 +1,5 @@
+redo-ifchange ${1%.o}.c ../../conf/cc ../../conf/cflags ../../conf/prefix
+read CC <../../conf/cc
+CFLAGS=$(cat ../../conf/cflags)
+read PREFIX <../../conf/prefix
+$CC $CFLAGS -I$PREFIX/include -c -o $3 ${1%.o}.c
index 38efb7c1447a9a8f48e9e7b25f7329bafccf794b22121e6572ffbf152b313130..a24c043398c3c682e618858090b7b70abbaf222656b178a9e82275cf001e6f40 100644 (file)
 // License along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include <assert.h>
-#include <errno.h>
 #include <math.h>
 #include <stdbool.h>
-#include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/time.h>
-#include <time.h>
 
 #include <yac/dec.h>
-#include <yac/dectai.h>
 #include <yac/err.h>
 #include <yac/items.h>
 
 #include "../lib/hex.h"
 #include "../lib/mmap.h"
+#include "../lib/printai.h"
 #include "../lib/uuid.h"
 
 static const size_t maxStrLen = 40;
@@ -45,9 +41,9 @@ static const char *ColourWhite = "\x1b[37m";
 static const char *ColourReset = "\x1b[0m";
 
 static void
-printIndent(const ptrdiff_t indent)
+printIndent(const size_t indent)
 {
-    for (ptrdiff_t i = 0; i < indent; i++) {
+    for (size_t i = 0; i < indent; i++) {
         fputs("  ", stdout);
     }
 }
@@ -59,9 +55,10 @@ static char OffFmt[16] = {0};
 static enum YACErr
 printer(
     const struct YACItems *items,
-    ptrdiff_t idx,
-    ptrdiff_t indent,
-    ptrdiff_t listIdx,
+    size_t idx,
+    size_t indent,
+    const bool inList,
+    size_t listIdx,
     const char *mapKey)
 {
     printf("%s%zd%s ", NoColour ? "" : ColourBlue, indent, NoColour ? "" : ColourReset);
@@ -72,7 +69,7 @@ printer(
         assert(indent >= 0);
     }
     printIndent(indent);
-    if (listIdx >= 0) {
+    if (inList) {
         fprintf(
             stdout,
             "%s%zu:%s ",
@@ -119,8 +116,8 @@ printer(
         indent++;
         idx = item->atom.v.list.head;
         listIdx = 0;
-        while (idx != -1) {
-            err = printer(items, idx, indent, listIdx, NULL);
+        while (idx != 0) {
+            err = printer(items, idx, indent, true, listIdx, NULL);
             if (err != YACErrNo) {
                 return err;
             }
@@ -143,12 +140,12 @@ printer(
             NoColour ? "" : ColourReset);
         indent++;
         idx = item->atom.v.list.head;
-        while (idx != -1) {
+        while (idx != 0) {
             str = strndup(
                 (const char *)(items->list[idx].atom.v.str.ptr),
                 items->list[idx].atom.v.str.len);
             idx = items->list[idx].next;
-            err = printer(items, idx, indent, -1, str);
+            err = printer(items, idx, indent, false, 0, str);
             free(str);
             if (err != YACErrNo) {
                 return err;
@@ -173,8 +170,8 @@ printer(
         indent++;
         idx++;
         listIdx = 0;
-        while (idx != -1) {
-            err = printer(items, idx, indent, listIdx, NULL);
+        while (idx != 0) {
+            err = printer(items, idx, indent, true, listIdx, NULL);
             if (err != YACErrNo) {
                 return err;
             }
@@ -192,46 +189,10 @@ printer(
         fputs("FLOAT: TODO\n", stdout);
         break;
     case YACItemTAI64: {
-        if ((item->atom.v.str.len) == 16) {
-            str = HexEnc(item->atom.v.str.ptr, item->atom.v.str.len);
-            fprintf(stdout, "TAI64NA(%s)\n", str);
-            free(str);
-            break;
-        }
-        switch (item->atom.v.str.len) {
-        case 8:
-            fputs("TAI64(", stdout);
-            break;
-        case 12:
-            fputs("TAI64N(", stdout);
-            break;
-        }
-        struct timeval tv;
-        err = YACTAI64ToTimeval(&tv, item->atom.v.str.ptr, item->atom.v.str.len);
-        if (err == YACErrTAI64BadNsec) {
-            str = HexEnc(item->atom.v.str.ptr, item->atom.v.str.len);
-            fprintf(stdout, "unrepresentable: %s)\n", str);
-            free(str);
-            break;
-        }
+        err = PrintTAI64(item->atom.v.str.ptr, item->atom.v.str.len);
         if (err != YACErrNo) {
             return err;
         }
-        time_t t = tv.tv_sec;
-        struct tm *tm = localtime(&t);
-        if (tm == NULL) {
-            str = HexEnc(item->atom.v.str.ptr, item->atom.v.str.len);
-            fprintf(stdout, "unrepresentable: %s)\n", str);
-            free(str);
-            break;
-        }
-        char human[20] = {0};
-        strftime(human, sizeof human, "%Y-%m-%d %H:%M:%S", tm);
-        fputs(human, stdout);
-        if ((item->atom.v.str.len) == 12) {
-            fprintf(stdout, ".%zu", tv.tv_usec);
-        }
-        fputs(")\n", stdout);
         break;
     }
     case YACItemBin: {
@@ -278,27 +239,33 @@ main(int argc, char **argv)
     size_t len = 0;
     unsigned char *buf = NULL;
     if (!Mmap(&buf, &len, argv[1])) {
-        fprintf(stderr, "%s\n", strerror(errno));
         exit(EXIT_FAILURE);
     }
-
     NoColour = getenv("NO_COLOR") != NULL;
-
     OffDigits = (int)(1 + floor(log10((double)len)));
     snprintf(OffFmt, sizeof OffFmt, "%%s%%0%dzd%%s ", OffDigits);
 
     struct YACItems items;
     YACItemsInit(&items);
-    ptrdiff_t off = 0;
+    size_t off = 0;
     enum YACErr err = YACItemsParse(&items, &off, buf, len);
     if (err != YACErrNo) {
         fprintf(stderr, "err: %s\n", YACErr2Str(err));
         return EXIT_FAILURE;
     }
-    err = printer(&items, 0, 0, -1, NULL);
+    err = printer(&items, 0, 0, false, 0, NULL);
     if (err != YACErrNo) {
         fprintf(stderr, "err: %s\n", YACErr2Str(err));
         return EXIT_FAILURE;
     }
+    printf("items: %zu  size: %zu\n", items.len, items.len * sizeof(struct YACItem));
+    if (getenv("DO_ENCODE") != NULL) {
+        unsigned char *dst = malloc(len);
+        assert(dst != NULL);
+        off = 0;
+        assert(YACItemsEncode(&items, 0, &off, dst, len));
+        assert(off == len);
+        assert(memcmp(dst, buf, len) == 0);
+    }
     return EXIT_SUCCESS;
 }
index c735e34360ce41e4cfe45a81d82302d3d18c477ea83de1399afe0d321cbbb0c9..7a01e52013db19fde01199c7d4b7d797b8ffd73594412fd06cdee86cc6bea2a2 100644 (file)
@@ -1,4 +1,4 @@
-deps="../lib/hex.o ../lib/mmap.o ../lib/uuid.o"
+deps="../lib/hex.o ../lib/mmap.o ../lib/printai.o ../lib/uuid.o"
 redo-ifchange $1.c $deps \
     ../../conf/cc ../../conf/cflags ../../conf/ldflags ../../conf/prefix
 read CC <../../conf/cc
index 1740c1e7cbaf95660a9832f0d49d3e39aa0d3d5c432b6d11c02cea6dbd8dcf81..ed2758b8e63724133c63596b3e7765e096b9d977351ad6f81292c3f074e28985 100644 (file)
 // License along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include <assert.h>
-#include <errno.h>
-#include <stddef.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/time.h>
-#include <time.h>
 
 #include <yac/dec.h>
-#include <yac/dectai.h>
 #include <yac/err.h>
 #include <yac/iter.h>
 
 #include "../lib/hex.h"
 #include "../lib/mmap.h"
+#include "../lib/printai.h"
 #include "../lib/uuid.h"
 
 static const size_t maxStrLen = 40;
 
 struct CbState {
-    ptrdiff_t indent;
+    int indent;
 };
 
 static enum YACErr
 myCb(
     const unsigned char *key,
     const size_t keyLen,
-    const ptrdiff_t idx,
+    const bool inList,
+    const size_t idx,
     void *cbState,
     struct YACAtom *atom,
-    ptrdiff_t *off,
+    size_t *off,
     const unsigned char *buf,
     const size_t len)
 {
@@ -53,14 +51,14 @@ myCb(
         state->indent--;
         assert(state->indent >= 0);
     }
-    printf("%04zd ", *off);
-    for (ptrdiff_t i = 0; i < state->indent; i++) {
+    printf("%04zu ", *off);
+    for (int i = 0; i < state->indent; i++) {
         fputs("  ", stdout);
     }
     if (key != NULL) {
         fwrite(key, keyLen, 1, stdout);
         fputs(": ", stdout);
-    } else if (idx > -1) {
+    } else if (inList) {
         fprintf(stdout, "%zu: ", idx);
     }
 
@@ -119,46 +117,10 @@ myCb(
         fputs("FLOAT: TODO\n", stdout);
         break;
     case YACItemTAI64:
-        if ((atom->v.str.len) == 16) {
-            hex = HexEnc(atom->v.str.ptr, atom->v.str.len);
-            fprintf(stdout, "TAI64NA(%s)\n", hex);
-            free(hex);
-            break;
-        }
-        switch (atom->v.str.len) {
-        case 8:
-            fputs("TAI64(", stdout);
-            break;
-        case 12:
-            fputs("TAI64N(", stdout);
-            break;
-        }
-        struct timeval tv;
-        err = YACTAI64ToTimeval(&tv, atom->v.str.ptr, atom->v.str.len);
-        if (err == YACErrTAI64BadNsec) {
-            hex = HexEnc(atom->v.str.ptr, atom->v.str.len);
-            fprintf(stdout, "unrepresentable: %s)\n", hex);
-            free(hex);
-            break;
-        }
+        err = PrintTAI64(atom->v.str.ptr, atom->v.str.len);
         if (err != YACErrNo) {
             return err;
         }
-        time_t t = tv.tv_sec;
-        struct tm *tm = localtime(&t);
-        if (tm == NULL) {
-            hex = HexEnc(atom->v.str.ptr, atom->v.str.len);
-            fprintf(stdout, "unrepresentable: %s)\n", hex);
-            free(hex);
-            break;
-        }
-        char human[20] = {0};
-        strftime(human, sizeof human, "%Y-%m-%d %H:%M:%S", tm);
-        fputs(human, stdout);
-        if ((atom->v.str.len) == 12) {
-            fprintf(stdout, ".%zu", tv.tv_usec);
-        }
-        fputs(")\n", stdout);
         break;
     case YACItemBin: {
         const size_t l = (atom->v.str.len > maxStrLen) ? maxStrLen : atom->v.str.len;
@@ -197,20 +159,20 @@ main(int argc, char **argv)
     size_t len = 0;
     unsigned char *buf = NULL;
     if (!Mmap(&buf, &len, argv[1])) {
-        fprintf(stderr, "%s\n", strerror(errno));
         exit(EXIT_FAILURE);
     }
     struct YACAtom atom;
     memset(&atom, 0, sizeof(struct YACAtom));
-    ptrdiff_t off = 0;
-    struct YACErrAndLen errLen = YACAtomDecode(&atom, buf, len);
-    if (errLen.err != YACErrNo) {
-        fprintf(stderr, "err: %s\n", YACErr2Str(errLen.err));
+    size_t off = 0;
+    size_t got = 0;
+    enum YACErr err = YACAtomDecode(&got, &atom, buf, len);
+    if (err != YACErrNo) {
+        fprintf(stderr, "err: %s\n", YACErr2Str(err));
         return EXIT_FAILURE;
     }
-    off += errLen.len;
+    off += got;
     struct CbState cbState = {.indent = 0};
-    enum YACErr err = myCb(NULL, 0, -1, &cbState, &atom, &off, buf, len);
+    err = myCb(NULL, 0, false, 0, &cbState, &atom, &off, buf, len);
     if (err != YACErrNo) {
         fprintf(stderr, "err: %s\n", YACErr2Str(err));
         return EXIT_FAILURE;
index 3fdc61346ad8ea42639153c4639e210459b708b3384cf49c6fd305773c9fced3..9f9b1e3798809341f8367094639b45605e92235f036467b859607024d61ce2a6 100644 (file)
@@ -1,4 +1,4 @@
-deps="../lib/hex.o ../lib/mmap.o ../lib/uuid.o"
+deps="../lib/hex.o ../lib/mmap.o ../lib/printai.o ../lib/uuid.o"
 redo-ifchange $1.c $deps \
     ../../conf/cc ../../conf/cflags ../../conf/ldflags ../../conf/prefix
 read CC <../../conf/cc
index c30329eb0d8da0670298cb1fd136de4f3eda4fe109a4109aedaf23067e087597..3e5405477efcab4dc4abceb4df0bea4b1b4e424361a68ba7f79afc95654bab71 100644 (file)
@@ -1,20 +1,22 @@
 #include <assert.h>
 #include <stdbool.h>
-#include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/time.h>
+#include <time.h>
 #include <unistd.h>
 
 #include <yac/atoms.h>
 #include <yac/enc.h>
 #include <yac/enctai.h>
 
+static size_t Off = 0;
+static size_t Got = 0;
+
 static void
-adder(size_t *off, const ptrdiff_t add)
+adder(const bool ok)
 {
-    assert(add > 0);
-    (*off) += (size_t)add;
+    assert(ok);
+    Off += Got;
 }
 
 int
@@ -25,211 +27,195 @@ main(int argc, char **argv)
     assert(buf != NULL);
     unsigned char *bin = malloc(1 << 16);
     assert(bin != NULL);
-    size_t off = 0;
 
-    adder(&off, YACAtomMapEncode(buf + off, len - off)); // .
+    adder(YACAtomMapEncode(&Got, buf + Off, len - Off)); // .
 
     adder(
-        &off, YACAtomStrEncode(buf + off, len - off, (const unsigned char *)"nil", 3));
-    adder(&off, YACAtomNILEncode(buf + off, len - off));
+        YACAtomStrEncode(&Got, buf + Off, len - Off, (const unsigned char *)"nil", 3));
+    adder(YACAtomNILEncode(&Got, buf + Off, len - Off));
 
     adder(
-        &off, YACAtomStrEncode(buf + off, len - off, (const unsigned char *)"str", 3));
-    adder(&off, YACAtomMapEncode(buf + off, len - off)); // .str
+        YACAtomStrEncode(&Got, buf + Off, len - Off, (const unsigned char *)"str", 3));
+    adder(YACAtomMapEncode(&Got, buf + Off, len - Off)); // .str
 
     adder(
-        &off, YACAtomStrEncode(buf + off, len - off, (const unsigned char *)"bin", 3));
-    adder(&off, YACAtomListEncode(buf + off, len - off)); // .str.bin
-    adder(&off, YACAtomBinEncode(buf + off, len - off, (const unsigned char *)"", 0));
+        YACAtomStrEncode(&Got, buf + Off, len - Off, (const unsigned char *)"bin", 3));
+    adder(YACAtomListEncode(&Got, buf + Off, len - Off)); // .str.bin
+    adder(YACAtomBinEncode(&Got, buf + Off, len - Off, (const unsigned char *)"", 0));
     memset(bin, '0', 60);
-    adder(&off, YACAtomBinEncode(buf + off, len - off, bin, 60));
+    adder(YACAtomBinEncode(&Got, buf + Off, len - Off, bin, 60));
     memset(bin, '1', 61);
-    adder(&off, YACAtomBinEncode(buf + off, len - off, bin, 61));
+    adder(YACAtomBinEncode(&Got, buf + Off, len - Off, bin, 61));
     memset(bin, '2', 255);
-    adder(&off, YACAtomBinEncode(buf + off, len - off, bin, 255));
+    adder(YACAtomBinEncode(&Got, buf + Off, len - Off, bin, 255));
     memset(bin, '3', 1024);
-    adder(&off, YACAtomBinEncode(buf + off, len - off, bin, 1024));
+    adder(YACAtomBinEncode(&Got, buf + Off, len - Off, bin, 1024));
     memset(bin, '4', 1 << 16);
-    adder(&off, YACAtomBinEncode(buf + off, len - off, bin, 1 << 16));
-    adder(&off, YACAtomEOCEncode(buf + off, len - off)); // .str.bin
+    adder(YACAtomBinEncode(&Got, buf + Off, len - Off, bin, 1 << 16));
+    adder(YACAtomEOCEncode(&Got, buf + Off, len - Off)); // .str.bin
 
     adder(
-        &off, YACAtomStrEncode(buf + off, len - off, (const unsigned char *)"utf8", 4));
-    adder(
-        &off,
-        YACAtomStrEncode(
-            buf + off, len - off, (const unsigned char *)"привет Ð¼Ð¸Ñ€", 19));
-    adder(&off, YACAtomEOCEncode(buf + off, len - off)); // .str
+        YACAtomStrEncode(&Got, buf + Off, len - Off, (const unsigned char *)"utf8", 4));
+    adder(YACAtomStrEncode(
+        &Got, buf + Off, len - Off, (const unsigned char *)"привет Ð¼Ð¸Ñ€", 19));
+    adder(YACAtomEOCEncode(&Got, buf + Off, len - Off)); // .str
 
     adder(
-        &off, YACAtomStrEncode(buf + off, len - off, (const unsigned char *)"blob", 4));
-    adder(&off, YACAtomListEncode(buf + off, len - off)); // .blob
+        YACAtomStrEncode(&Got, buf + Off, len - Off, (const unsigned char *)"blob", 4));
+    adder(YACAtomListEncode(&Got, buf + Off, len - Off)); // .blob
 
-    adder(&off, YACAtomBlobEncode(buf + off, len - off, 12)); // .blob.0
+    adder(YACAtomBlobEncode(&Got, buf + Off, len - Off, 12)); // .blob.0
     memset(bin, '5', 1);
-    adder(&off, YACAtomBinEncode(buf + off, len - off, bin, 1));
+    adder(YACAtomBinEncode(&Got, buf + Off, len - Off, bin, 1));
 
-    adder(&off, YACAtomBlobEncode(buf + off, len - off, 12)); // .blob.1
+    adder(YACAtomBlobEncode(&Got, buf + Off, len - Off, 12)); // .blob.1
     memset(bin, '6', 12);
-    adder(&off, YACAtomChunkEncode(buf + off, len - off, bin, 12));
-    adder(&off, YACAtomBinEncode(buf + off, len - off, NULL, 0));
+    adder(YACAtomChunkEncode(&Got, buf + Off, len - Off, bin, 12));
+    adder(YACAtomBinEncode(&Got, buf + Off, len - Off, NULL, 0));
 
-    adder(&off, YACAtomBlobEncode(buf + off, len - off, 12)); // .blob.2
+    adder(YACAtomBlobEncode(&Got, buf + Off, len - Off, 12)); // .blob.2
     memset(bin, '7', 12);
-    adder(&off, YACAtomChunkEncode(buf + off, len - off, bin, 12));
-    adder(&off, YACAtomBinEncode(buf + off, len - off, bin, 1));
-
-    adder(&off, YACAtomBlobEncode(buf + off, len - off, 5)); // .blob.3
-    adder(
-        &off,
-        YACAtomChunkEncode(buf + off, len - off, (const unsigned char *)"12345", 5));
-    adder(
-        &off,
-        YACAtomChunkEncode(buf + off, len - off, (const unsigned char *)"67890", 5));
-    adder(&off, YACAtomBinEncode(buf + off, len - off, (const unsigned char *)"-", 1));
-
-    adder(&off, YACAtomEOCEncode(buf + off, len - off)); // .blob
-
-    adder(
-        &off, YACAtomStrEncode(buf + off, len - off, (const unsigned char *)"bool", 4));
-    adder(&off, YACAtomListEncode(buf + off, len - off)); // .bool
-    adder(&off, YACAtomBoolEncode(buf + off, len - off, true));
-    adder(&off, YACAtomBoolEncode(buf + off, len - off, false));
-    adder(&off, YACAtomEOCEncode(buf + off, len - off)); // .bool
-
-    adder(
-        &off, YACAtomStrEncode(buf + off, len - off, (const unsigned char *)"ints", 4));
-    adder(&off, YACAtomMapEncode(buf + off, len - off)); // .ints
-
-    adder(
-        &off, YACAtomStrEncode(buf + off, len - off, (const unsigned char *)"neg", 3));
-    adder(&off, YACAtomListEncode(buf + off, len - off)); // .ints.neg
-    adder(&off, YACAtomSintEncode(buf + off, len - off, -1));
-    adder(&off, YACAtomSintEncode(buf + off, len - off, -2));
-    adder(&off, YACAtomSintEncode(buf + off, len - off, -32));
-    adder(&off, YACAtomSintEncode(buf + off, len - off, -33));
-    adder(&off, YACAtomSintEncode(buf + off, len - off, -123));
-    adder(&off, YACAtomSintEncode(buf + off, len - off, -1234));
-    adder(&off, YACAtomSintEncode(buf + off, len - off, -12345678));
-    adder(
-        &off,
-        YACAtomRawEncode(
-            buf + off,
-            len - off,
-            YACAtomIntNeg10,
-            (const unsigned char *)"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
-            10));
-    adder(&off, YACAtomEOCEncode(buf + off, len - off)); // .ints.neg
-
-    adder(
-        &off, YACAtomStrEncode(buf + off, len - off, (const unsigned char *)"pos", 3));
-    adder(&off, YACAtomListEncode(buf + off, len - off)); // .ints.pos
-    adder(&off, YACAtomUintEncode(buf + off, len - off, 0));
-    adder(&off, YACAtomUintEncode(buf + off, len - off, 1));
-    adder(&off, YACAtomUintEncode(buf + off, len - off, 31));
-    adder(&off, YACAtomUintEncode(buf + off, len - off, 32));
-    adder(&off, YACAtomUintEncode(buf + off, len - off, 123));
-    adder(&off, YACAtomUintEncode(buf + off, len - off, 1234));
-    adder(&off, YACAtomUintEncode(buf + off, len - off, 12345678));
-    adder(
-        &off,
-        YACAtomRawEncode(
-            buf + off,
-            len - off,
-            YACAtomIntPos11,
-            (const unsigned char *)"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
-            11));
-    adder(&off, YACAtomEOCEncode(buf + off, len - off)); // .ints.pos
-
-    adder(&off, YACAtomEOCEncode(buf + off, len - off)); // .ints
-
-    adder(
-        &off, YACAtomStrEncode(buf + off, len - off, (const unsigned char *)"uuid", 4));
-    adder(
-        &off,
-        YACAtomUUIDEncode(
-            buf + off,
-            len - off,
-            (const unsigned char
-                 *)"\x0e\x87\x5e\x3f\xd3\x85\x49\xeb\x87\xb4\xbe\x42\xd6\x41\xc3\x67"));
-
-    adder(
-        &off,
-        YACAtomStrEncode(buf + off, len - off, (const unsigned char *)"dates", 5));
-    adder(&off, YACAtomListEncode(buf + off, len - off)); // .dates
+    adder(YACAtomChunkEncode(&Got, buf + Off, len - Off, bin, 12));
+    adder(YACAtomBinEncode(&Got, buf + Off, len - Off, bin, 1));
+
+    adder(YACAtomBlobEncode(&Got, buf + Off, len - Off, 5)); // .blob.3
+    adder(YACAtomChunkEncode(
+        &Got, buf + Off, len - Off, (const unsigned char *)"12345", 5));
+    adder(YACAtomChunkEncode(
+        &Got, buf + Off, len - Off, (const unsigned char *)"67890", 5));
+    adder(YACAtomBinEncode(&Got, buf + Off, len - Off, (const unsigned char *)"-", 1));
+
+    adder(YACAtomEOCEncode(&Got, buf + Off, len - Off)); // .blob
+
+    adder(
+        YACAtomStrEncode(&Got, buf + Off, len - Off, (const unsigned char *)"bool", 4));
+    adder(YACAtomListEncode(&Got, buf + Off, len - Off)); // .bool
+    adder(YACAtomBoolEncode(&Got, buf + Off, len - Off, true));
+    adder(YACAtomBoolEncode(&Got, buf + Off, len - Off, false));
+    adder(YACAtomEOCEncode(&Got, buf + Off, len - Off)); // .bool
+
+    adder(
+        YACAtomStrEncode(&Got, buf + Off, len - Off, (const unsigned char *)"ints", 4));
+    adder(YACAtomMapEncode(&Got, buf + Off, len - Off)); // .ints
+
+    adder(
+        YACAtomStrEncode(&Got, buf + Off, len - Off, (const unsigned char *)"neg", 3));
+    adder(YACAtomListEncode(&Got, buf + Off, len - Off)); // .ints.neg
+    adder(YACAtomSintEncode(&Got, buf + Off, len - Off, -1));
+    adder(YACAtomSintEncode(&Got, buf + Off, len - Off, -2));
+    adder(YACAtomSintEncode(&Got, buf + Off, len - Off, -32));
+    adder(YACAtomSintEncode(&Got, buf + Off, len - Off, -33));
+    adder(YACAtomSintEncode(&Got, buf + Off, len - Off, -123));
+    adder(YACAtomSintEncode(&Got, buf + Off, len - Off, -1234));
+    adder(YACAtomSintEncode(&Got, buf + Off, len - Off, -12345678));
+    adder(YACAtomRawEncode(
+        &Got,
+        buf + Off,
+        len - Off,
+        YACAtomIntNeg10,
+        (const unsigned char *)"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
+        10));
+    adder(YACAtomEOCEncode(&Got, buf + Off, len - Off)); // .ints.neg
+
+    adder(
+        YACAtomStrEncode(&Got, buf + Off, len - Off, (const unsigned char *)"pos", 3));
+    adder(YACAtomListEncode(&Got, buf + Off, len - Off)); // .ints.pos
+    adder(YACAtomUintEncode(&Got, buf + Off, len - Off, 0));
+    adder(YACAtomUintEncode(&Got, buf + Off, len - Off, 1));
+    adder(YACAtomUintEncode(&Got, buf + Off, len - Off, 31));
+    adder(YACAtomUintEncode(&Got, buf + Off, len - Off, 32));
+    adder(YACAtomUintEncode(&Got, buf + Off, len - Off, 123));
+    adder(YACAtomUintEncode(&Got, buf + Off, len - Off, 1234));
+    adder(YACAtomUintEncode(&Got, buf + Off, len - Off, 12345678));
+    adder(YACAtomRawEncode(
+        &Got,
+        buf + Off,
+        len - Off,
+        YACAtomIntPos11,
+        (const unsigned char *)"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+        11));
+    adder(YACAtomEOCEncode(&Got, buf + Off, len - Off)); // .ints.pos
+
+    adder(YACAtomEOCEncode(&Got, buf + Off, len - Off)); // .ints
+
+    adder(
+        YACAtomStrEncode(&Got, buf + Off, len - Off, (const unsigned char *)"uuid", 4));
+    adder(YACAtomUUIDEncode(
+        &Got,
+        buf + Off,
+        len - Off,
+        (const unsigned char
+             *)"\x0e\x87\x5e\x3f\xd3\x85\x49\xeb\x87\xb4\xbe\x42\xd6\x41\xc3\x67"));
+
+    adder(YACAtomStrEncode(
+        &Got, buf + Off, len - Off, (const unsigned char *)"dates", 5));
+    adder(YACAtomListEncode(&Got, buf + Off, len - Off)); // .dates
     {
-        struct timeval tv;
+        struct timespec tv;
         tv.tv_sec = 1234567890;
         unsigned char tai[12] = {0};
-        YACTimevalToTAI64(tai, &tv);
-        adder(&off, YACAtomTAI64Encode(buf + off, len - off, tai, 8));
-
-        tv.tv_usec = 456;
-        YACTimevalToTAI64(tai, &tv);
-        adder(&off, YACAtomTAI64Encode(buf + off, len - off, tai, 12));
-
-        adder(
-            &off,
-            YACAtomRawEncode(
-                buf + off,
-                len - off,
-                YACAtomTAI64N,
-                (const unsigned char
-                     *)"\x40\x00\x00\x00\x49\x96\x02\xF4\x00\x06\xF8\x55",
-                12));
-
-        adder(
-            &off,
-            YACAtomRawEncode(
-                buf + off,
-                len - off,
-                YACAtomTAI64NA,
-                (const unsigned char
-                     *)"\x40\x00\x00\x00\x49\x96\x02\xF4\x00\x06\xF8\x55\x07\x5B\xCD\x15",
-                16));
+        assert(YACTimespecToTAI64(tai, &tv));
+        adder(YACAtomTAI64Encode(&Got, buf + Off, len - Off, tai, 8));
+
+        tv.tv_nsec = 456000;
+        assert(YACTimespecToTAI64(tai, &tv));
+        adder(YACAtomTAI64Encode(&Got, buf + Off, len - Off, tai, 12));
+
+        adder(YACAtomRawEncode(
+            &Got,
+            buf + Off,
+            len - Off,
+            YACAtomTAI64N,
+            (const unsigned char *)"\x40\x00\x00\x00\x49\x96\x02\xF4\x00\x06\xF8\x55",
+            12));
+
+        adder(YACAtomRawEncode(
+            &Got,
+            buf + Off,
+            len - Off,
+            YACAtomTAI64NA,
+            (const unsigned char
+                 *)"\x40\x00\x00\x00\x49\x96\x02\xF4\x00\x06\xF8\x55\x07\x5B\xCD\x15",
+            16));
     }
-    adder(&off, YACAtomEOCEncode(buf + off, len - off)); // .dates
-
-    adder(
-        &off,
-        YACAtomStrEncode(buf + off, len - off, (const unsigned char *)"floats", 6));
-    adder(&off, YACAtomListEncode(buf + off, len - off)); // .floats
-    adder(
-        &off,
-        YACAtomRawEncode(
-            buf + off,
-            len - off,
-            YACAtomFloat32,
-            (const unsigned char *)"\x01\x02\x03\x04",
-            4));
-    adder(&off, YACAtomEOCEncode(buf + off, len - off)); // .floats
-
-    adder(
-        &off,
-        YACAtomStrEncode(buf + off, len - off, (const unsigned char *)"empties", 7));
-    adder(&off, YACAtomListEncode(buf + off, len - off)); // .empties
-    adder(&off, YACAtomListEncode(buf + off, len - off));
-    adder(&off, YACAtomEOCEncode(buf + off, len - off));
-    adder(&off, YACAtomMapEncode(buf + off, len - off));
-    adder(&off, YACAtomEOCEncode(buf + off, len - off));
-    adder(&off, YACAtomBlobEncode(buf + off, len - off, 123));
-    adder(&off, YACAtomBinEncode(buf + off, len - off, NULL, 0));
+    adder(YACAtomEOCEncode(&Got, buf + Off, len - Off)); // .dates
+
+    adder(YACAtomStrEncode(
+        &Got, buf + Off, len - Off, (const unsigned char *)"floats", 6));
+    adder(YACAtomListEncode(&Got, buf + Off, len - Off)); // .floats
+    adder(YACAtomRawEncode(
+        &Got,
+        buf + Off,
+        len - Off,
+        YACAtomFloat32,
+        (const unsigned char *)"\x01\x02\x03\x04",
+        4));
+    adder(YACAtomEOCEncode(&Got, buf + Off, len - Off)); // .floats
+
+    adder(YACAtomStrEncode(
+        &Got, buf + Off, len - Off, (const unsigned char *)"empties", 7));
+    adder(YACAtomListEncode(&Got, buf + Off, len - Off)); // .empties
+    adder(YACAtomListEncode(&Got, buf + Off, len - Off));
+    adder(YACAtomEOCEncode(&Got, buf + Off, len - Off));
+    adder(YACAtomMapEncode(&Got, buf + Off, len - Off));
+    adder(YACAtomEOCEncode(&Got, buf + Off, len - Off));
+    adder(YACAtomBlobEncode(&Got, buf + Off, len - Off, 123));
+    adder(YACAtomBinEncode(&Got, buf + Off, len - Off, NULL, 0));
     memset(bin, '\x00', 16);
-    adder(&off, YACAtomUUIDEncode(buf + off, len - off, bin));
-    adder(
-        &off,
-        YACAtomRawEncode(
-            buf + off,
-            len - off,
-            YACAtomTAI64,
-            (const unsigned char *)"\x00\x00\x00\x00\x00\x00\x00\x00",
-            8));
-    adder(&off, YACAtomEOCEncode(buf + off, len - off)); // .empties
-
-    adder(&off, YACAtomEOCEncode(buf + off, len - off)); // .
+    adder(YACAtomUUIDEncode(&Got, buf + Off, len - Off, bin));
+    adder(YACAtomRawEncode(
+        &Got,
+        buf + Off,
+        len - Off,
+        YACAtomTAI64,
+        (const unsigned char *)"\x00\x00\x00\x00\x00\x00\x00\x00",
+        8));
+    adder(YACAtomEOCEncode(&Got, buf + Off, len - Off)); // .empties
+
+    adder(YACAtomEOCEncode(&Got, buf + Off, len - Off)); // .
 
     free(bin);
-    assert(write(STDOUT_FILENO, buf, off) == (ssize_t)off);
+    assert(write(STDOUT_FILENO, buf, Off) == (ssize_t)Off);
     free(buf);
 
     return EXIT_SUCCESS;
index 73f571569f3ceabbbad4546ac8d7ca08417e18843b5bee628d6237ebe8557fe6..588744a0eefb1e04ef413f3bd36b0781e01de54f355653c11863f2b3e0ae30ec 100644 (file)
 #include "frombe.h"
 #include "utf8.h"
 
-struct YACErrAndLen
-YACAtomDecode(struct YACAtom *atom, const unsigned char *buf, const size_t len)
+enum YACErr
+YACAtomDecode(
+    size_t *got,
+    struct YACAtom *atom,
+    const unsigned char *buf,
+    const size_t len)
 {
     atom->v.str.ptr = NULL;
     atom->v.str.len = 0;
-    struct YACErrAndLen ret = {.err = YACErrInvalid, .len = 1};
+    (*got) = 1;
     if (len < 1) {
-        ret.err = YACErrNotEnough;
-        return ret;
+        return YACErrNotEnough;
     }
     atom->tag = buf[0];
 
     if ((atom->tag & YACAtomStrings) > 0) {
         atom->typ = ((atom->tag & YACAtomIsUTF8) == 0) ? YACItemBin : YACItemStr;
-        size_t l = atom->tag & 63;
+        uint64_t l = atom->tag & 63;
         size_t ll = 0;
         switch (l) {
         case 61:
@@ -50,56 +53,55 @@ YACAtomDecode(struct YACAtom *atom, const unsigned char *buf, const size_t len)
             break;
         }
         if (ll != 0) {
-            ret.len += ll;
-            if ((ptrdiff_t)len < ret.len) {
-                ret.err = YACErrNotEnough;
-                return ret;
+            (*got) += ll;
+            if (len < (*got)) {
+                return YACErrNotEnough;
             }
             l = yacFromBE(buf + 1, ll);
             if ((l < 61) || ((l < (1 << 8)) && (ll > 1)) ||
                 ((l < (1 << 16)) && (ll > 2))) {
-                ret.err = YACErrLenNonMinimal;
-                return ret;
-            }
-            if (l > ((uint64_t)(1) << 60)) {
-                ret.err = YACErrLenTooBig;
-                return ret;
+                return YACErrLenNonMinimal;
             }
         }
-        ret.len += l;
-        if ((ptrdiff_t)len < ret.len) {
-            ret.err = YACErrNotEnough;
-            return ret;
+        if (l > SIZE_MAX) {
+            return YACErrLenTooBig;
         }
-        atom->v.str.len = l;
+        const size_t ls = (size_t)l;
+        (*got) += ls;
+        if ((*got) <= ls) {
+            return YACErrLenTooBig;
+        }
+        if (len < (*got)) {
+            return YACErrNotEnough;
+        }
+        atom->v.str.len = ls;
         atom->v.str.ptr = buf + 1 + ll;
         if (atom->typ == YACItemStr) {
+            if (l > PTRDIFF_MAX) {
+                return YACErrLenTooBig;
+            }
             size_t cpl = 0;
             uint32_t cp = YACUTF8InvalidCp;
             for (size_t n = 0; n < l;) {
-                cpl = YACUTF8CpDecode(&cp, atom->v.str.ptr + n, l - n);
+                cpl = YACUTF8CpDecode(&cp, atom->v.str.ptr + (ptrdiff_t)n, l - n);
                 if (cp == YACUTF8InvalidCp) {
-                    ret.err = YACErrBadUTF8;
-                    return ret;
+                    return YACErrBadUTF8;
                 }
                 n += cpl;
             }
         }
-        ret.err = YACErrNo;
-        return ret;
+        return YACErrNo;
     }
 
     if ((atom->tag >= YACAtomInt0) && (atom->tag < YACAtomInt0 + 32)) {
-        atom->v.pint = (uint64_t)(atom->tag - YACAtomInt0);
         atom->typ = YACItemPint;
-        ret.err = YACErrNo;
-        return ret;
+        atom->v.pint = (uint64_t)(atom->tag - YACAtomInt0);
+        return YACErrNo;
     }
     if ((atom->tag >= YACAtomIntN1) && (atom->tag < YACAtomIntN1 + 32)) {
-        atom->v.nint = -1 - (int64_t)(atom->tag - YACAtomIntN1);
         atom->typ = YACItemNint;
-        ret.err = YACErrNo;
-        return ret;
+        atom->v.nint = -1 - (int64_t)(atom->tag - YACAtomIntN1);
+        return YACErrNo;
     }
     switch (atom->tag & 0xF0) {
     case YACAtomIntPos1:
@@ -107,14 +109,12 @@ YACAtomDecode(struct YACAtom *atom, const unsigned char *buf, const size_t len)
         atom->typ = ((atom->tag & YACAtomIntNeg1) == YACAtomIntNeg1) ? YACItemNint :
                                                                        YACItemPint;
         const size_t l = (atom->tag & 0x0F) + 1;
-        ret.len += l;
-        if ((ptrdiff_t)len < ret.len) {
-            ret.err = YACErrNotEnough;
-            return ret;
+        (*got) += l;
+        if (len < (*got)) {
+            return YACErrNotEnough;
         }
         if (buf[1] == 0) {
-            ret.err = YACErrIntNonMinimal;
-            return ret;
+            return YACErrIntNonMinimal;
         }
         if (l > 8) {
             atom->typ = YACItemRaw;
@@ -123,15 +123,19 @@ YACAtomDecode(struct YACAtom *atom, const unsigned char *buf, const size_t len)
         } else {
             atom->v.pint = yacFromBE(buf + 1, l);
             if ((atom->v.pint) < 32) {
-                ret.err = YACErrIntNonMinimal;
-                return ret;
+                return YACErrIntNonMinimal;
             }
             if (atom->typ == YACItemNint) {
-                atom->v.nint = -1 - (int64_t)(atom->v.pint);
+                if (atom->v.pint >= ((uint64_t)1 << 63)) {
+                    atom->typ = YACItemRaw;
+                    atom->v.str.len = l;
+                    atom->v.str.ptr = buf + 1;
+                } else {
+                    atom->v.nint = -1 - (int64_t)(atom->v.pint);
+                }
             }
         }
-        ret.err = YACErrNo;
-        return ret;
+        return YACErrNo;
     }
     }
 
@@ -150,10 +154,9 @@ YACAtomDecode(struct YACAtom *atom, const unsigned char *buf, const size_t len)
         break;
     case YACAtomUUID:
         atom->typ = YACItemUUID;
-        ret.len += 16;
-        if ((ptrdiff_t)len < ret.len) {
-            ret.err = YACErrNotEnough;
-            return ret;
+        (*got) += 16;
+        if (len < (*got)) {
+            return YACErrNotEnough;
         }
         atom->v.uuid = buf + 1;
         break;
@@ -164,23 +167,22 @@ YACAtomDecode(struct YACAtom *atom, const unsigned char *buf, const size_t len)
     case YACAtomMap:
         atom->typ = YACItemMap;
         break;
-    case YACAtomBlob:
+    case YACAtomBlob: {
         atom->typ = YACItemBlob;
-        ret.len += 8;
-        if ((ptrdiff_t)len < ret.len) {
-            ret.err = YACErrNotEnough;
-            return ret;
+        (*got) += 8;
+        if (len < (*got)) {
+            return YACErrNotEnough;
         }
-        atom->v.blob.chunkLen = yacFromBE(buf + 1, 8);
-        if (atom->v.blob.chunkLen == 0) {
-            ret.err = YACErrBlobBadLen;
-            return ret;
+        const uint64_t chunkLen = yacFromBE(buf + 1, 8);
+        if (chunkLen > SIZE_MAX) {
+            return YACErrLenTooBig;
         }
-        if (atom->v.blob.chunkLen > ((uint64_t)(1) << 60)) {
-            ret.err = YACErrNotEnough;
-            return ret;
+        if (chunkLen == 0) {
+            return YACErrBlobBadLen;
         }
+        atom->v.blob.chunkLen = (size_t)chunkLen;
         break;
+    }
 
     case YACAtomFloat16:
     case YACAtomFloat32:
@@ -206,10 +208,9 @@ YACAtomDecode(struct YACAtom *atom, const unsigned char *buf, const size_t len)
             break;
         }
         atom->typ = YACItemFloat;
-        ret.len += l;
-        if ((ptrdiff_t)len < ret.len) {
-            ret.err = YACErrNotEnough;
-            return ret;
+        (*got) += l;
+        if (len < (*got)) {
+            return YACErrNotEnough;
         }
         atom->typ = YACItemRaw;
         atom->v.str.len = l;
@@ -233,41 +234,35 @@ YACAtomDecode(struct YACAtom *atom, const unsigned char *buf, const size_t len)
             break;
         }
         atom->typ = YACItemTAI64;
-        ret.len += l;
-        if ((ptrdiff_t)len < ret.len) {
-            ret.err = YACErrNotEnough;
-            return ret;
+        (*got) += l;
+        if (len < (*got)) {
+            return YACErrNotEnough;
         }
         atom->v.str.len = l;
         atom->v.str.ptr = buf + 1;
         uint64_t v = yacFromBE(buf + 1, 8);
-        if (v > ((uint64_t)(1) << 63)) {
-            ret.err = YACErrTAI64TooBig;
-            return ret;
+        if (v > ((uint64_t)1 << 63)) {
+            return YACErrTAI64TooBig;
         }
         switch (l) {
         case 12:
             v = yacFromBE(buf + 1 + 8, 4);
             if (v > 999999999) {
-                ret.err = YACErrTAI64BadNsec;
-                return ret;
+                return YACErrTAI64BadNsec;
             }
             break;
         case 16:
             v = yacFromBE(buf + 1 + 8 + 4, 4);
             if (v > 999999999) {
-                ret.err = YACErrTAI64BadAsec;
-                return ret;
+                return YACErrTAI64BadAsec;
             }
             break;
         }
         break;
     }
     default:
-        ret.err = YACErrUnknownType;
-        return ret;
+        return YACErrUnknownType;
     }
 
-    ret.err = YACErrNo;
-    return ret;
+    return YACErrNo;
 }
index 4b8b3a67900350142c85b408fea5344cc0783e159e534fab5d01f4ca1226232c..1930301892dad3061831b6e8d824643e4bcba7e4304272b934e7216529ac87ad 100644 (file)
@@ -89,11 +89,11 @@ struct YACAtom {
         uint64_t pint;
         int64_t nint;
         struct {
-            ptrdiff_t head;
+            size_t head;
             size_t len;
         } list;
         struct {
-            uint64_t chunkLen;
+            size_t chunkLen;
             size_t chunks;
         } blob;
         struct {
@@ -106,13 +106,11 @@ struct YACAtom {
     char _pad[3];
 };
 
-struct YACErrAndLen {
-    ptrdiff_t len;
-    enum YACErr err;
-    char _pad[4];
-};
-
-struct YACErrAndLen
-YACAtomDecode(struct YACAtom *atom, const unsigned char *buf, const size_t len);
+enum YACErr
+YACAtomDecode(
+    size_t *got,
+    struct YACAtom *atom,
+    const unsigned char *buf,
+    const size_t len);
 
 #endif // YAC_DEC_H
index b3d27dc75833f6c5bc0fc58877a2fca7a0d372c243712b0818d4607a1690e5dd..f36b993c0ce2dc5a0bf2f3b6b6fbeadcfdaa34e3364a34b3c124219a818d4120 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <stddef.h>
 #include <stdint.h>
-#include <sys/time.h>
+#include <time.h>
 
 #include "dectai.h"
 #include "err.h"
 #include "leapsecs.h"
 
 enum YACErr
-YACTAI64ToTimeval(struct timeval *tv, const unsigned char *buf, const size_t len)
+YACTAI64ToTimespec(struct timespec *tv, const unsigned char *buf, const size_t len)
 {
     if (len > 12) {
         return YACErrTAI64BadAsec;
     }
     int64_t v = (int64_t)yacFromBE(buf, 8);
     v -= 0x4000000000000000;
+    if (v <= 0) {
+        return YACErrTAI64InPast;
+    }
     {
         int64_t diff = 0;
         for (size_t i = 0; i < YACLeapsecsN; i++) {
@@ -40,13 +43,16 @@ YACTAI64ToTimeval(struct timeval *tv, const unsigned char *buf, const size_t len
         }
         v -= diff;
     }
+    if (v <= 0) {
+        return YACErrTAI64InPast;
+    }
+    if (((uint64_t)1 << ((sizeof(time_t) * 8) - 1)) < (uint64_t)v) {
+        return YACErrTAI64TooBig;
+    }
     tv->tv_sec = (time_t)v;
     if (len > 8) {
         uint32_t n = (uint32_t)yacFromBE(buf + 8, 4);
-        if ((n % 1000) != 0) {
-            return YACErrTAI64BadNsec;
-        }
-        tv->tv_usec = n / 1000;
+        tv->tv_nsec = n;
     }
     return YACErrNo;
 }
index a12a82f99ea4ebb93e7a96587833dc4766c970e60be7d05ae4d9b96750f170d5..efc573b8d1d08353ebcb565558f162dec87d0197f4fe01fa9b80e7ab07176600 100644 (file)
@@ -3,11 +3,11 @@
 #define YAC_DECTAI_H
 
 #include <stddef.h>
-#include <sys/time.h>
+#include <time.h>
 
 #include "err.h"
 
 enum YACErr
-YACTAI64ToTimeval(struct timeval *tv, const unsigned char *buf, const size_t len);
+YACTAI64ToTimespec(struct timespec *tv, const unsigned char *buf, const size_t len);
 
 #endif // YAC_DECTAI_H
index 765d4526f7841fbb52005cdff891ffae71c770acc93c69c001a4a53923a83b25..b737e25c1266a419720ecbd4daa929067f6a22e7324689fa8da14efa5f4aebb3 100644 (file)
 #include "enc.h"
 #include "tobe.h"
 
-ptrdiff_t
-YACAtomEOCEncode(unsigned char *buf, const size_t cap)
+bool
+YACAtomEOCEncode(size_t *len, unsigned char *buf, const size_t cap)
 {
+    (*len) = 1;
     if (cap < 1) {
-        return -1;
+        return false;
     }
     buf[0] = YACAtomEOC;
-    return 1;
+    return true;
 }
 
-ptrdiff_t
-YACAtomNILEncode(unsigned char *buf, const size_t cap)
+bool
+YACAtomNILEncode(size_t *len, unsigned char *buf, const size_t cap)
 {
+    (*len) = 1;
     if (cap < 1) {
-        return -1;
+        return false;
     }
     buf[0] = YACAtomNIL;
-    return 1;
+    return true;
 }
 
-ptrdiff_t
-YACAtomBoolEncode(unsigned char *buf, const size_t cap, const bool v)
+bool
+YACAtomBoolEncode(size_t *len, unsigned char *buf, const size_t cap, const bool v)
 {
+    (*len) = 1;
     if (cap < 1) {
-        return -1;
+        return false;
     }
     buf[0] = v ? YACAtomTrue : YACAtomFalse;
-    return 1;
+    return true;
 }
 
-ptrdiff_t
-YACAtomUUIDEncode(unsigned char *buf, const size_t cap, const unsigned char v[16])
+bool
+YACAtomUUIDEncode(
+    size_t *len,
+    unsigned char *buf,
+    const size_t cap,
+    const unsigned char v[16])
 {
-    if (cap < 1 + 16) {
-        return -(1 + 16);
+    (*len) = 1 + 16;
+    if (cap < (1 + 16)) {
+        return false;
     }
     buf[0] = YACAtomUUID;
     memcpy(buf + 1, v, 16);
-    return 1 + 16;
+    return true;
 }
 
-static ptrdiff_t
-yacAtomIntEncode(unsigned char *buf, const size_t cap, const uint64_t v)
+static bool
+yacAtomIntEncode(size_t *len, unsigned char *buf, const size_t cap, const uint64_t v)
 {
     if (v < 32) {
+        (*len) = 1;
         if (cap < 1) {
-            return -1;
+            return false;
         }
         buf[0] = (unsigned char)v;
-        return 1;
+        return true;
     }
     size_t bits = 8;
     size_t l = 0;
     for (;;) {
-        if (v < (((uint64_t)1) << bits)) {
+        if (v < ((uint64_t)1 << bits)) {
             break;
         }
         l++;
         bits += 8;
     }
     if (cap < (1 + l)) {
-        return -(1 + (ptrdiff_t)l);
+        return false;
     }
     buf[0] = (unsigned char)l;
     l++;
     yacToBE(buf + 1, l, v);
-    return 1 + (ptrdiff_t)l;
+    (*len) = 1 + l;
+    return true;
 }
 
-ptrdiff_t
-YACAtomUintEncode(unsigned char *buf, const size_t cap, uint64_t v)
+bool
+YACAtomUintEncode(size_t *len, unsigned char *buf, const size_t cap, uint64_t v)
 {
-    ptrdiff_t ret = yacAtomIntEncode(buf, cap, v);
-    if (ret < 0) {
-        return ret;
+    bool ok = yacAtomIntEncode(len, buf, cap, v);
+    if (ok) {
+        buf[0] |= (v < 32) ? YACAtomInt0 : YACAtomIntPos1;
     }
-    buf[0] |= (v < 32) ? YACAtomInt0 : YACAtomIntPos1;
-    return ret;
+    return ok;
 }
 
-ptrdiff_t
-YACAtomSintEncode(unsigned char *buf, const size_t cap, int64_t v)
+bool
+YACAtomSintEncode(size_t *len, unsigned char *buf, const size_t cap, int64_t v)
 {
     if (v >= 0) {
-        return YACAtomUintEncode(buf, cap, (uint64_t)v);
+        return YACAtomUintEncode(len, buf, cap, (uint64_t)v);
     }
     const uint64_t vp = (uint64_t)(-(v + 1));
-    ptrdiff_t ret = yacAtomIntEncode(buf, cap, vp);
-    if (ret < 0) {
-        return ret;
+    bool ok = yacAtomIntEncode(len, buf, cap, vp);
+    if (ok) {
+        buf[0] |= (vp < 32) ? YACAtomIntN1 : YACAtomIntNeg1;
     }
-    buf[0] |= (vp < 32) ? YACAtomIntN1 : YACAtomIntNeg1;
-    return ret;
+    return ok;
 }
 
-ptrdiff_t
-YACAtomListEncode(unsigned char *buf, const size_t cap)
+bool
+YACAtomListEncode(size_t *len, unsigned char *buf, const size_t cap)
 {
+    (*len) = 1;
     if (cap < 1) {
-        return -1;
+        return false;
     }
     buf[0] = YACAtomList;
-    return 1;
+    return true;
 }
 
-ptrdiff_t
-YACAtomMapEncode(unsigned char *buf, const size_t cap)
+bool
+YACAtomMapEncode(size_t *len, unsigned char *buf, const size_t cap)
 {
+    (*len) = 1;
     if (cap < 1) {
-        return -1;
+        return false;
     }
     buf[0] = YACAtomMap;
-    return 1;
+    return true;
 }
 
-ptrdiff_t
-YACAtomBlobEncode(unsigned char *buf, const size_t cap, const size_t chunkLen)
+bool
+YACAtomBlobEncode(
+    size_t *len,
+    unsigned char *buf,
+    const size_t cap,
+    const size_t chunkLen)
 {
+    (*len) = 1 + 8;
     if (cap < 1 + 8) {
-        return -(1 + 8);
+        return false;
     }
     buf[0] = YACAtomBlob;
-    yacToBE(buf + 1, 8, chunkLen);
-    return 1 + 8;
+    yacToBE(buf + 1, 8, (uint64_t)chunkLen);
+    return true;
 }
 
-static ptrdiff_t
+static bool
 yacAtomStrEncode(
+    size_t *len,
     unsigned char *buf,
     const size_t cap,
     const unsigned char *src,
-    const size_t l,
+    const size_t srcLen,
     const bool utf8)
 {
-    unsigned char lv = 0;
-    size_t ll = 0;
+    unsigned char lVal = 0;
+    size_t lLen = 0;
     unsigned char lBuf[8] = {0};
-    if (l >= (((uint64_t)1) << 16)) {
-        lv = 63;
-        ll = 8;
-        yacToBE(lBuf, 8, l);
-    } else if (l >= (((uint64_t)1) << 8)) {
-        lv = 62;
-        ll = 2;
-        yacToBE(lBuf, 2, l);
-    } else if (l > 60) {
-        lv = 61;
-        ll = 1;
-        lBuf[0] = (unsigned char)(l & 0xFF);
+    if (srcLen >= ((uint64_t)1 << 16)) {
+        lVal = 63;
+        lLen = 8;
+        yacToBE(lBuf, 8, (uint64_t)srcLen);
+    } else if (srcLen >= ((uint64_t)1 << 8)) {
+        lVal = 62;
+        lLen = 2;
+        yacToBE(lBuf, 2, (uint64_t)srcLen);
+    } else if (srcLen > 60) {
+        lVal = 61;
+        lLen = 1;
+        lBuf[0] = (unsigned char)(srcLen & 0xFF);
     } else {
-        lv = (unsigned char)l;
+        lVal = (unsigned char)srcLen;
+    }
+    (*len) = 1 + lLen + srcLen;
+    if ((*len) <= srcLen) {
+        (*len) = 0;
+        return false;
     }
-    if (cap < (1 + ll + l)) {
-        return -(ptrdiff_t)(1 + ll + l);
+    if (cap < (*len)) {
+        return false;
     }
-    buf[0] = YACAtomStrings | lv;
+    buf[0] = YACAtomStrings | lVal;
     if (utf8) {
         buf[0] |= YACAtomIsUTF8;
     }
-    memcpy(buf + 1, lBuf, ll);
-    memcpy(buf + 1 + ll, src, l);
-    return (ptrdiff_t)(1 + ll + l);
+    memcpy(buf + 1, lBuf, lLen);
+    memcpy(buf + 1 + lLen, src, srcLen);
+    return true;
 }
 
-ptrdiff_t
+bool
 YACAtomStrEncode(
+    size_t *len,
     unsigned char *buf,
     const size_t cap,
     const unsigned char *src,
-    const size_t len)
+    const size_t srcLen)
 {
-    return yacAtomStrEncode(buf, cap, src, len, true);
+    return yacAtomStrEncode(len, buf, cap, src, srcLen, true);
 }
 
-ptrdiff_t
+bool
 YACAtomBinEncode(
+    size_t *len,
     unsigned char *buf,
     const size_t cap,
     const unsigned char *src,
-    const size_t len)
+    const size_t srcLen)
 {
-    return yacAtomStrEncode(buf, cap, src, len, false);
+    return yacAtomStrEncode(len, buf, cap, src, srcLen, false);
 }
 
-ptrdiff_t
+bool
 YACAtomChunkEncode(
+    size_t *len,
     unsigned char *buf,
     const size_t cap,
     const unsigned char *src,
-    const size_t len)
+    const size_t srcLen)
 {
-    if (cap < (1 + len)) {
-        return -(ptrdiff_t)(1 + len);
+    (*len) = 1 + srcLen;
+    if ((*len) <= srcLen) {
+        (*len) = 0;
+        return false;
+    }
+    if (cap < (*len)) {
+        return false;
     }
     buf[0] = YACAtomNIL;
-    memcpy(buf + 1, src, len);
-    return (ptrdiff_t)(1 + len);
+    memcpy(buf + 1, src, srcLen);
+    return true;
 }
 
-ptrdiff_t
+bool
 YACAtomTAI64Encode(
+    size_t *len,
     unsigned char *buf,
     const size_t cap,
     const unsigned char *src,
-    const size_t len)
+    const size_t srcLen)
 {
-    switch (len) {
+    (*len) = 1 + srcLen;
+    if (cap < (*len)) {
+        return false;
+    }
+    switch (srcLen) {
     case 8:
         buf[0] = YACAtomTAI64;
         break;
@@ -241,25 +275,28 @@ YACAtomTAI64Encode(
     default:
         return 0;
     }
-    if (cap < (1 + len)) {
-        return -(ptrdiff_t)(1 + len);
-    }
-    memcpy(buf + 1, src, len);
-    return (ptrdiff_t)(1 + len);
+    memcpy(buf + 1, src, srcLen);
+    return true;
 }
 
-ptrdiff_t
+bool
 YACAtomRawEncode(
+    size_t *len,
     unsigned char *buf,
     const size_t cap,
     const unsigned char typ,
     const unsigned char *src,
-    const size_t len)
+    const size_t srcLen)
 {
-    if (cap < (1 + len)) {
-        return -(ptrdiff_t)(1 + len);
+    (*len) = 1 + srcLen;
+    if ((*len) <= srcLen) {
+        (*len) = 0;
+        return false;
+    }
+    if (cap < (*len)) {
+        return false;
     }
     buf[0] = typ;
-    memcpy(buf + 1, src, len);
-    return (ptrdiff_t)(1 + len);
+    memcpy(buf + 1, src, srcLen);
+    return true;
 }
index 78dfa8b5feba57b47fadc4e02ad9a694ac6b88b48320ffd3987b8e877145420d..fcb551df6f0a0be43301c18d9e71c0b172637c217e720db08c41cdb71a9748df 100644 (file)
@@ -5,67 +5,80 @@
 #include <stddef.h>
 #include <stdint.h>
 
-ptrdiff_t
-YACAtomEOCEncode(unsigned char *buf, const size_t cap);
+bool
+YACAtomEOCEncode(size_t *len, unsigned char *buf, const size_t cap);
 
-ptrdiff_t
-YACAtomNILEncode(unsigned char *buf, const size_t cap);
+bool
+YACAtomNILEncode(size_t *len, unsigned char *buf, const size_t cap);
 
-ptrdiff_t
-YACAtomBoolEncode(unsigned char *buf, const size_t cap, const bool v);
+bool
+YACAtomBoolEncode(size_t *len, unsigned char *buf, const size_t cap, const bool v);
 
-ptrdiff_t
-YACAtomUUIDEncode(unsigned char *buf, const size_t cap, const unsigned char v[16]);
+bool
+YACAtomUUIDEncode(
+    size_t *len,
+    unsigned char *buf,
+    const size_t cap,
+    const unsigned char v[16]);
 
-ptrdiff_t
-YACAtomUintEncode(unsigned char *buf, const size_t cap, uint64_t v);
+bool
+YACAtomUintEncode(size_t *len, unsigned char *buf, const size_t cap, uint64_t v);
 
-ptrdiff_t
-YACAtomSintEncode(unsigned char *buf, const size_t cap, int64_t v);
+bool
+YACAtomSintEncode(size_t *len, unsigned char *buf, const size_t cap, int64_t v);
 
-ptrdiff_t
-YACAtomListEncode(unsigned char *buf, const size_t cap);
+bool
+YACAtomListEncode(size_t *len, unsigned char *buf, const size_t cap);
 
-ptrdiff_t
-YACAtomMapEncode(unsigned char *buf, const size_t cap);
+bool
+YACAtomMapEncode(size_t *len, unsigned char *buf, const size_t cap);
 
-ptrdiff_t
-YACAtomBlobEncode(unsigned char *buf, const size_t cap, const size_t chunkLen);
+bool
+YACAtomBlobEncode(
+    size_t *len,
+    unsigned char *buf,
+    const size_t cap,
+    const size_t chunkLen);
 
-ptrdiff_t
+bool
 YACAtomStrEncode(
+    size_t *len,
     unsigned char *buf,
     const size_t cap,
     const unsigned char *src,
-    const size_t len);
+    const size_t srcLen);
 
-ptrdiff_t
+bool
 YACAtomBinEncode(
+    size_t *len,
     unsigned char *buf,
     const size_t cap,
     const unsigned char *src,
-    const size_t len);
+    const size_t srcLen);
 
-ptrdiff_t
+bool
 YACAtomChunkEncode(
+    size_t *len,
     unsigned char *buf,
     const size_t cap,
     const unsigned char *src,
-    const size_t len);
+    const size_t srcLen);
 
-ptrdiff_t
+bool
 YACAtomTAI64Encode(
+    size_t *len,
     unsigned char *buf,
     const size_t cap,
     const unsigned char *src,
-    const size_t len);
+    const size_t srcLen);
 
-ptrdiff_t
+bool
 YACAtomRawEncode(
+    size_t *len,
     unsigned char *buf,
     const size_t cap,
     const unsigned char typ,
     const unsigned char *src,
-    const size_t len);
+    const size_t srcLen);
 
 #endif // YAC_ENC_H
index 6595a71752fe0ff76dea150918d7a34159fa3e7b39bd3173ae89cbea1e3c8e14..32afb5649234d45d54cdb74b9321ccaa6a45de8cec3457717f63cbd1e88d440e 100644 (file)
 // You should have received a copy of the GNU Lesser General Public
 // License along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-#include <stddef.h>
 #include <stdint.h>
-#include <sys/time.h>
+#include <time.h>
 
 #include "enctai.h"
 #include "leapsecs.h"
 #include "tobe.h"
 
-void
-YACTimevalToTAI64(unsigned char *buf, const struct timeval *tv)
+bool
+YACTimespecToTAI64(unsigned char *buf, const struct timespec *tv)
 {
     int64_t v = (int64_t)(tv->tv_sec);
     int64_t diff = YACLeapsecs1972;
-    for (size_t i = 0; i < sizeof YACLeapsecsN; i++) {
+    for (size_t i = 0; i < YACLeapsecsN; i++) {
         if (v > YACLeapsecs[i]) {
             diff += YACLeapsecsN - i;
             break;
         }
     }
-    v += 0x4000000000000000 + diff;
-    yacToBE(buf, 8, (uint64_t)v);
-    if (tv->tv_usec != 0) {
-        yacToBE(buf + 8, 4, (uint64_t)(tv->tv_usec) * 1000);
+    uint64_t val = (uint64_t)v + 0x4000000000000000 + (uint64_t)diff;
+    if (val <= (uint64_t)v) {
+        return false;
     }
+    yacToBE(buf, 8, val);
+    if (tv->tv_nsec != 0) {
+        yacToBE(buf + 8, 4, (uint64_t)(tv->tv_nsec));
+    }
+    return true;
 }
index 7487ae6be4d51d741c88c694c40632692aac982dea258cb536b9fe702e0f912a..e965fe93b08e5be436731f66af99fc793c1042670f196c76f799d4d4946428ff 100644 (file)
@@ -1,9 +1,10 @@
 #ifndef YAC_ENCTAI_H
 #define YAC_ENCTAI_H
 
-#include <sys/time.h>
+#include <stdbool.h>
+#include <time.h>
 
-void
-YACTimevalToTAI64(unsigned char *buf, const struct timeval *tv);
+bool
+YACTimespecToTAI64(unsigned char *buf, const struct timespec *tv);
 
 #endif // YAC_ENCTAI_H
index 0967b34eb7a0354a7bd0fdc9a2e98f62dc5f54c3bf5c8ac6480030b5a59ea037..204066525ae9eb6365e8267434f3213cd40d83857221db224faffbd8a9915d88 100644 (file)
@@ -18,8 +18,6 @@ YACErr2Str(const enum YACErr err)
         return "LenTooBig";
     case YACErrBadUTF8:
         return "BadUTF8";
-    case YACErrIntZeroByte:
-        return "IntZeroByte";
     case YACErrIntNonMinimal:
         return "IntNonMinimal";
     case YACErrBlobBadLen:
@@ -34,6 +32,8 @@ YACErr2Str(const enum YACErr err)
         return "TAI64BadNsec";
     case YACErrTAI64BadAsec:
         return "TAI64BadAsec";
+    case YACErrTAI64InPast:
+        return "TAI64InPast";
     case YACErrMapBadKey:
         return "MapBadKey";
     case YACErrMapNoVal:
index e940f11b22b200cc02d84196d844d3206a87a4a754bd2d126e7464382de04a3d..1f35725f8ed63f6fa96ee803db6deebe1d2c5ee0285c95ce248db197984c9bee 100644 (file)
@@ -51,7 +51,6 @@ enum YACErr {
     YACErrLenNonMinimal,
     YACErrLenTooBig,
     YACErrBadUTF8,
-    YACErrIntZeroByte,
     YACErrIntNonMinimal,
     YACErrBlobBadLen,
     YACErrBlobBadAtom,
@@ -59,6 +58,7 @@ enum YACErr {
     YACErrTAI64TooBig,
     YACErrTAI64BadNsec,
     YACErrTAI64BadAsec,
+    YACErrTAI64InPast,
     YACErrMapBadKey,
     YACErrMapNoVal,
     YACErrMapUnordered,
index 52e2ed20f5dacc0b8be631fe48ec9bf085bf09612ebe691ac4fe383c479b98be..a13b56517a6c21e03366adb94a323f20e703845d3d4a24368e44dbd292dadbdb 100644 (file)
 // You should have received a copy of the GNU Lesser General Public
 // License along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+#include <assert.h>
 #include <stdbool.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -23,7 +25,7 @@
 #include "err.h"
 #include "items.h"
 
-static const ptrdiff_t yacItemsPoolGrowLen = 32;
+static const ptrdiff_t yacItemsPoolGrowLen = 64;
 
 enum YACErr
 YACItemsInit(struct YACItems *items)
@@ -40,16 +42,25 @@ YACItemsInit(struct YACItems *items)
 enum YACErr
 yacItemsGrow(struct YACItems *items)
 {
-    items->cap += yacItemsPoolGrowLen;
-    if (items->cap <= 0) {
+    if (items->cap == -1) {
+        return YACErrNoMem;
+    }
+    if ((SIZE_MAX - yacItemsPoolGrowLen) < (size_t)(items->cap)) {
         return YACErrNoMem;
     }
+    items->cap += yacItemsPoolGrowLen;
+    {
+        const ptrdiff_t possibleN = SIZE_MAX / sizeof(struct YACItem);
+        if (items->cap > possibleN) {
+            return YACErrNoMem;
+        }
+    }
     const size_t size = (size_t)(items->cap) * sizeof(struct YACItem);
     items->list = realloc(items->list, size);
     if (items->list == NULL) {
         return YACErrNoMem;
     }
-    const size_t begin = (size_t)(items->len) * sizeof(struct YACItem);
+    const size_t begin = items->len * sizeof(struct YACItem);
     memset((unsigned char *)(items->list) + begin, 0, size - begin);
     return YACErrNo;
 }
@@ -57,52 +68,56 @@ yacItemsGrow(struct YACItems *items)
 static enum YACErr
 yacItemsAdd(
     struct YACItems *items,
-    ptrdiff_t *off,
+    size_t *off,
     const unsigned char *buf,
     const size_t len)
 {
     enum YACErr err = YACErrInvalid;
-    if (items->len == items->cap) {
+    if (items->len == (size_t)(items->cap)) {
         err = yacItemsGrow(items);
         if (err != YACErrNo) {
             return err;
         }
     }
     struct YACItem *item = &(items->list[items->len]);
-    item->next = -1;
+    item->next = 0;
     item->off = *off;
-    struct YACErrAndLen errLen =
-        YACAtomDecode(&(item->atom), buf + *off, len - (size_t)(*off));
-    if (errLen.err != YACErrNo) {
+    size_t got = 0;
+    assert(len >= (*off));
+    err = YACAtomDecode(&got, &(item->atom), buf + *off, len - (*off));
+    if (err != YACErrNo) {
         return err;
     }
-    (*off) += errLen.len;
-    items->len++;
-    if (items->len <= 0) {
-        return YACErrNoMem;
+    if ((SIZE_MAX - got) < (*off)) {
+        return YACErrLenTooBig;
     }
+    (*off) += got;
+    items->len++;
     return YACErrNo;
 }
 
 enum YACErr
 YACItemsParse(
     struct YACItems *items,
-    ptrdiff_t *off,
+    size_t *off,
     const unsigned char *buf,
     const size_t len)
 {
-    ptrdiff_t item = items->len;
+    size_t item = items->len;
     enum YACErr err = yacItemsAdd(items, off, buf, len);
     if (err != YACErrNo) {
         return err;
     }
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wswitch-enum"
     switch (items->list[item].atom.typ) {
+#pragma clang diagnostic pop
     case YACItemList: {
         items->list[item].atom.v.list.head = item + 1;
         items->list[item].atom.v.list.len = 0;
-        ptrdiff_t prev = -1;
-        ptrdiff_t cur = -1;
-        ptrdiff_t idx = item;
+        size_t prev = 0;
+        size_t cur = 0;
+        size_t idx = item;
         for (;;) {
             err = YACItemsParse(items, off, buf, len);
             if (err != YACErrNo) {
@@ -111,11 +126,11 @@ YACItemsParse(
             cur = idx + 1;
             if (items->list[cur].atom.typ == YACItemEOC) {
                 if (items->list[item].atom.v.list.len == 0) {
-                    items->list[item].atom.v.list.head = -1;
+                    items->list[item].atom.v.list.head = 0;
                 }
                 return YACErrNo;
             }
-            if (prev != -1) {
+            if (prev != 0) {
                 items->list[prev].next = cur;
             }
             prev = cur;
@@ -126,9 +141,9 @@ YACItemsParse(
     case YACItemMap: {
         items->list[item].atom.v.list.head = item + 1;
         items->list[item].atom.v.list.len = 0;
-        ptrdiff_t idx = item;
-        ptrdiff_t prev = -1;
-        ptrdiff_t cur = -1;
+        size_t idx = item;
+        size_t prev = 0;
+        size_t cur = 0;
         size_t prevKeyLen = 0;
         const unsigned char *prevKey = NULL;
         for (;;) {
@@ -137,27 +152,17 @@ YACItemsParse(
                 return err;
             }
             cur = idx + 1;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wswitch-enum"
             switch (items->list[cur].atom.typ) {
+#pragma clang diagnostic pop
             case YACItemEOC:
                 if (items->list[item].atom.v.list.len == 0) {
-                    items->list[item].atom.v.list.head = -1;
+                    items->list[item].atom.v.list.head = 0;
                 }
                 return YACErrNo;
             case YACItemStr:
                 break;
-            case YACItemNIL:
-            case YACItemFalse:
-            case YACItemTrue:
-            case YACItemUUID:
-            case YACItemPint:
-            case YACItemNint:
-            case YACItemList:
-            case YACItemMap:
-            case YACItemBlob:
-            case YACItemFloat:
-            case YACItemTAI64:
-            case YACItemBin:
-            case YACItemRaw:
             default:
                 return YACErrMapBadKey;
             }
@@ -173,7 +178,7 @@ YACItemsParse(
             }
             prevKeyLen = items->list[cur].atom.v.str.len;
             prevKey = items->list[cur].atom.v.str.ptr;
-            if (prev != -1) {
+            if (prev != 0) {
                 items->list[prev].next = cur;
             }
             prev = cur;
@@ -194,10 +199,10 @@ YACItemsParse(
     }
     case YACItemBlob: {
         items->list[item].atom.v.blob.chunks = 0;
-        const ptrdiff_t chunkLen = (ptrdiff_t)(items->list[item].atom.v.blob.chunkLen);
-        ptrdiff_t idx = item;
-        ptrdiff_t prev = -1;
-        ptrdiff_t cur = -1;
+        const size_t chunkLen = items->list[item].atom.v.blob.chunkLen;
+        size_t idx = item;
+        size_t prev = 0;
+        size_t cur = 0;
         bool eoc = false;
         while (!eoc) {
             err = YACItemsParse(items, off, buf, len);
@@ -206,40 +211,33 @@ YACItemsParse(
             }
             cur = idx + 1;
             struct YACAtom *atom = &(items->list[cur].atom);
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wswitch-enum"
             switch (atom->typ) {
+#pragma clang diagnostic pop
             case YACItemNIL:
-                if (((ptrdiff_t)len - *off) <= chunkLen) {
-                    atom->v.str.len = (size_t)chunkLen;
+                atom->v.str.len = chunkLen;
+                assert(len >= (*off));
+                if ((len - (*off)) <= chunkLen) {
                     return YACErrNotEnough;
                 }
                 atom->typ = YACItemBin;
                 atom->v.str.ptr = buf + *off;
-                atom->v.str.len = (size_t)chunkLen;
+                if ((SIZE_MAX - chunkLen) < (*off)) {
+                    return YACErrLenTooBig;
+                }
                 (*off) += chunkLen;
                 break;
             case YACItemBin:
-                if ((ptrdiff_t)(atom->v.str.len) >= chunkLen) {
+                if (atom->v.str.len >= chunkLen) {
                     return YACErrBlobBadTerm;
                 }
                 eoc = true;
                 break;
-            case YACItemEOC:
-            case YACItemFalse:
-            case YACItemTrue:
-            case YACItemUUID:
-            case YACItemPint:
-            case YACItemNint:
-            case YACItemList:
-            case YACItemMap:
-            case YACItemBlob:
-            case YACItemFloat:
-            case YACItemTAI64:
-            case YACItemStr:
-            case YACItemRaw:
             default:
                 return YACErrBlobBadAtom;
             }
-            if (prev != -1) {
+            if (prev != 0) {
                 items->list[prev].next = cur;
             }
             prev = cur;
@@ -248,173 +246,170 @@ YACItemsParse(
         }
         break;
     }
-    case YACItemEOC:
-    case YACItemNIL:
-    case YACItemFalse:
-    case YACItemTrue:
-    case YACItemUUID:
-    case YACItemPint:
-    case YACItemNint:
-    case YACItemFloat:
-    case YACItemTAI64:
-    case YACItemBin:
-    case YACItemStr:
-    case YACItemRaw:
     default:
         break;
     }
     return YACErrNo;
 }
 
-ptrdiff_t
+bool
 YACItemsEncode(
-    struct YACItems *items,
-    ptrdiff_t idx,
-    ptrdiff_t *off,
+    const struct YACItems *items,
+    size_t idx,
+    size_t *off,
     unsigned char *buf,
     const size_t cap)
 {
-    struct YACItem *item = &(items->list[idx]);
-    ptrdiff_t diff = 0;
+    const struct YACItem *item = &(items->list[idx]);
+    size_t got = 0;
+    bool ok = false;
+    assert(cap >= (*off));
     switch (item->atom.typ) {
     case YACItemEOC:
-        return -1;
+        return false;
     case YACItemNIL:
-        diff = YACAtomNILEncode(buf + *off, cap - (size_t)(*off));
+        ok = YACAtomNILEncode(&got, buf + *off, cap - (*off));
         break;
     case YACItemFalse:
-        diff = YACAtomBoolEncode(buf + *off, cap - (size_t)(*off), false);
+        ok = YACAtomBoolEncode(&got, buf + *off, cap - (*off), false);
         break;
     case YACItemTrue:
-        diff = YACAtomBoolEncode(buf + *off, cap - (size_t)(*off), true);
+        ok = YACAtomBoolEncode(&got, buf + *off, cap - (*off), true);
         break;
     case YACItemUUID:
-        diff = YACAtomUUIDEncode(buf + *off, cap - (size_t)(*off), item->atom.v.uuid);
+        ok = YACAtomUUIDEncode(&got, buf + *off, cap - (*off), item->atom.v.uuid);
         break;
     case YACItemPint:
-        diff = YACAtomUintEncode(buf + *off, cap - (size_t)(*off), item->atom.v.pint);
+        ok = YACAtomUintEncode(&got, buf + *off, cap - (*off), item->atom.v.pint);
         break;
     case YACItemNint:
-        diff = YACAtomSintEncode(buf + *off, cap - (size_t)(*off), item->atom.v.nint);
+        ok = YACAtomSintEncode(&got, buf + *off, cap - (*off), item->atom.v.nint);
         break;
     case YACItemList:
-        diff = YACAtomListEncode(buf + *off, cap - (size_t)(*off));
-        if (diff < 0) {
-            return diff;
+        ok = YACAtomListEncode(&got, buf + *off, cap - (*off));
+        if (!ok) {
+            return false;
+        }
+        if ((SIZE_MAX - got) < (*off)) {
+            return false;
         }
-        (*off) += diff;
+        (*off) += got;
         idx = item->atom.v.list.head;
-        while (idx != -1) {
-            diff = YACItemsEncode(items, idx, off, buf, cap);
-            if (diff < 0) {
-                return diff;
+        while (idx != 0) {
+            ok = YACItemsEncode(items, idx, off, buf, cap);
+            if (!ok) {
+                return false;
             }
             idx = items->list[idx].next;
         }
-        diff = YACAtomEOCEncode(buf + *off, cap - (size_t)(*off));
+        assert(cap >= (*off));
+        ok = YACAtomEOCEncode(&got, buf + *off, cap - (*off));
         break;
     case YACItemMap:
-        diff = YACAtomMapEncode(buf + *off, cap - (size_t)(*off));
-        if (diff < 0) {
-            return diff;
+        ok = YACAtomMapEncode(&got, buf + *off, cap - (*off));
+        if (!ok) {
+            return false;
+        }
+        if ((SIZE_MAX - got) < (*off)) {
+            return false;
         }
-        (*off) += diff;
+        (*off) += got;
         idx = item->atom.v.list.head;
-        while (idx != -1) {
-            diff = YACItemsEncode(items, idx, off, buf, cap);
-            if (diff < 0) {
-                return diff;
+        while (idx != 0) {
+            ok = YACItemsEncode(items, idx, off, buf, cap);
+            if (!ok) {
+                return false;
             }
             idx = items->list[idx].next;
         }
-        diff = YACAtomEOCEncode(buf + *off, cap - (size_t)(*off));
+        ok = YACAtomEOCEncode(&got, buf + *off, cap - (*off));
         break;
     case YACItemBlob: {
-        size_t chunkLen = (size_t)(item->atom.v.blob.chunkLen);
-        diff = YACAtomBlobEncode(
-            buf + *off, cap - (size_t)(*off), item->atom.v.blob.chunkLen);
-        if (diff < 0) {
-            return diff;
+        const size_t chunkLen = (item->atom.v.blob.chunkLen);
+        ok = YACAtomBlobEncode(&got, buf + *off, cap - (*off), chunkLen);
+        if (!ok) {
+            return 0;
         }
-        (*off) += diff;
+        if ((SIZE_MAX - got) < (*off)) {
+            return false;
+        }
+        (*off) += got;
         for (;;) {
             idx++;
             item = &(items->list[idx]);
             if (item->atom.v.str.len != chunkLen) {
                 break;
             }
-            diff = YACAtomChunkEncode(
+            assert(cap >= (*off));
+            ok = YACAtomChunkEncode(
+                &got,
                 buf + *off,
-                cap - (size_t)(*off),
+                cap - (*off),
                 item->atom.v.str.ptr,
                 item->atom.v.str.len);
-            if (diff < 0) {
-                return diff;
+            if (!ok) {
+                return false;
             }
-            (*off) += diff;
+            if ((SIZE_MAX - got) < (*off)) {
+                return false;
+            }
+            (*off) += got;
             continue;
         }
-        diff = YACAtomBinEncode(
-            buf + *off,
-            cap - (size_t)(*off),
-            item->atom.v.str.ptr,
-            item->atom.v.str.len);
+        assert(cap >= (*off));
+        ok = YACAtomBinEncode(
+            &got, buf + *off, cap - (*off), item->atom.v.str.ptr, item->atom.v.str.len);
         break;
     }
     case YACItemFloat:
-        return -1;
+        return false;
     case YACItemTAI64:
-        diff = YACAtomTAI64Encode(
-            buf + *off,
-            cap - (size_t)(*off),
-            item->atom.v.str.ptr,
-            item->atom.v.str.len);
+        ok = YACAtomTAI64Encode(
+            &got, buf + *off, cap - (*off), item->atom.v.str.ptr, item->atom.v.str.len);
         break;
     case YACItemBin:
-        diff = YACAtomBinEncode(
-            buf + *off,
-            cap - (size_t)(*off),
-            item->atom.v.str.ptr,
-            item->atom.v.str.len);
+        ok = YACAtomBinEncode(
+            &got, buf + *off, cap - (*off), item->atom.v.str.ptr, item->atom.v.str.len);
         break;
     case YACItemStr:
-        diff = YACAtomStrEncode(
-            buf + *off,
-            cap - (size_t)(*off),
-            item->atom.v.str.ptr,
-            item->atom.v.str.len);
+        ok = YACAtomStrEncode(
+            &got, buf + *off, cap - (*off), item->atom.v.str.ptr, item->atom.v.str.len);
         break;
     case YACItemRaw:
-        diff = YACAtomRawEncode(
+        ok = YACAtomRawEncode(
+            &got,
             buf + *off,
-            cap - (size_t)(*off),
+            cap - (*off),
             item->atom.tag,
             item->atom.v.str.ptr,
             item->atom.v.str.len);
         break;
     default:
-        return -1;
+        return false;
     }
-    if (diff < 0) {
-        return diff;
+    if (!ok) {
+        return false;
     }
-    (*off) += diff;
-    return 0;
+    if ((SIZE_MAX - got) < (*off)) {
+        return false;
+    }
+    (*off) += got;
+    return true;
 }
 
-ptrdiff_t
+size_t
 YACItemsGetByKeyLen(
-    struct YACItems *items,
-    const ptrdiff_t itemIdx,
+    const struct YACItems *items,
+    const size_t itemIdx,
     const char *key,
     const size_t keyLen)
 {
-    struct YACItem *item = &(items->list[itemIdx]);
+    const struct YACItem *item = &(items->list[itemIdx]);
     if (item->atom.typ != YACItemMap) {
-        return -1;
+        return 0;
     }
-    ptrdiff_t idx = item->atom.v.list.head;
-    while (idx != -1) {
+    size_t idx = item->atom.v.list.head;
+    while (idx != 0) {
         if ((items->list[idx].atom.v.str.len == keyLen) &&
             (memcmp(items->list[idx].atom.v.str.ptr, key, keyLen) == 0)) {
             return idx + 1;
@@ -422,41 +417,41 @@ YACItemsGetByKeyLen(
         idx = items->list[idx].next;
         idx = items->list[idx].next;
     }
-    return -1;
+    return 0;
 }
 
-ptrdiff_t
-YACItemsGetByKey(struct YACItems *items, const ptrdiff_t itemIdx, const char *key)
+size_t
+YACItemsGetByKey(const struct YACItems *items, const size_t itemIdx, const char *key)
 {
     return YACItemsGetByKeyLen(items, itemIdx, key, strlen(key));
 }
 
-ptrdiff_t
+size_t
 YACItemsGetByKeyAndType(
-    struct YACItems *items,
-    const ptrdiff_t itemIdx,
+    const struct YACItems *items,
+    const size_t itemIdx,
     const char *key,
     const enum YACItemType typ)
 {
-    ptrdiff_t idx = YACItemsGetByKey(items, itemIdx, key);
-    if ((idx == -1) || (items->list[idx].atom.typ != typ)) {
-        return -1;
+    const size_t idx = YACItemsGetByKey(items, itemIdx, key);
+    if ((idx == 0) || (items->list[idx].atom.typ != typ)) {
+        return 0;
     }
     return idx;
 }
 
 bool
-YACStrEqual(struct YACAtom *atom, const char *s)
+YACStrEqual(const struct YACAtom *atom, const char *s)
 {
     return (atom->v.str.len == strlen(s)) &&
            (memcmp(atom->v.str.ptr, s, atom->v.str.len) == 0);
 }
 
 bool
-YACListHasOnlyType(struct YACItems *items, ptrdiff_t idx, const enum YACItemType typ)
+YACListHasOnlyType(const struct YACItems *items, size_t idx, const enum YACItemType typ)
 {
     idx = items->list[idx].atom.v.list.head;
-    while (idx != -1) {
+    while (idx != 0) {
         if (items->list[idx].atom.typ != typ) {
             return false;
         }
@@ -466,10 +461,10 @@ YACListHasOnlyType(struct YACItems *items, ptrdiff_t idx, const enum YACItemType
 }
 
 bool
-YACMapHasOnlyType(struct YACItems *items, ptrdiff_t idx, const enum YACItemType typ)
+YACMapHasOnlyType(const struct YACItems *items, size_t idx, const enum YACItemType typ)
 {
     idx = items->list[idx].atom.v.list.head;
-    while (idx != -1) {
+    while (idx != 0) {
         idx = items->list[idx].next;
         if (items->list[idx].atom.typ != typ) {
             return false;
index 7645783236dc21e38534a3f562d9a9b8e6a1d8e5c883c5b6756c0ef80d6f1a84..47770a1e812cf184f70a32bdc4646f06fe9e2e1de7b4cdda1abd46f60a7001aa 100644 (file)
@@ -24,8 +24,8 @@
 // item, until its length is less than chunk len.
 // @end deftypevar
 struct YACItem {
-    ptrdiff_t off;
-    ptrdiff_t next;
+    size_t off;
+    size_t next;
     struct YACAtom atom;
 };
 
@@ -38,7 +38,7 @@ struct YACItem {
 // @end deftypevar
 struct YACItems {
     struct YACItem *list;
-    ptrdiff_t len;
+    size_t len;
     ptrdiff_t cap;
 };
 
@@ -51,42 +51,42 @@ yacItemsGrow(struct YACItems *);
 enum YACErr
 YACItemsParse(
     struct YACItems *,
-    ptrdiff_t *off,
+    size_t *off,
     const unsigned char *buf,
     const size_t len);
 
-ptrdiff_t
+bool
 YACItemsEncode(
-    struct YACItems *,
-    ptrdiff_t idx,
-    ptrdiff_t *off,
+    const struct YACItems *,
+    size_t idx,
+    size_t *off,
     unsigned char *buf,
     const size_t cap);
 
-ptrdiff_t
+size_t
 YACItemsGetByKeyLen(
-    struct YACItems *,
-    const ptrdiff_t itemIdx,
+    const struct YACItems *,
+    const size_t itemIdx,
     const char *key,
     const size_t keyLen);
 
-ptrdiff_t
-YACItemsGetByKey(struct YACItems *, const ptrdiff_t itemIdx, const char *key);
+size_t
+YACItemsGetByKey(const struct YACItems *, const size_t itemIdx, const char *key);
 
-ptrdiff_t
+size_t
 YACItemsGetByKeyAndType(
-    struct YACItems *,
-    const ptrdiff_t itemIdx,
+    const struct YACItems *,
+    const size_t itemIdx,
     const char *key,
     const enum YACItemType typ);
 
 bool
-YACStrEqual(struct YACAtom *, const char *s);
+YACStrEqual(const struct YACAtom *, const char *s);
 
 bool
-YACListHasOnlyType(struct YACItems *, ptrdiff_t idx, const enum YACItemType typ);
+YACListHasOnlyType(const struct YACItems *, size_t idx, const enum YACItemType typ);
 
 bool
-YACMapHasOnlyType(struct YACItems *, ptrdiff_t idx, const enum YACItemType typ);
+YACMapHasOnlyType(const struct YACItems *, size_t idx, const enum YACItemType typ);
 
 #endif // YAC_POOL_H
index 99cf5704b07c9e06a1728555ed50adac5ac32e3f26d7ee4a650c912b1c59d622..566fc73bf7c91c65f5d365a7210c78f67741cc87a5837adda5211c6bc21b935c 100644 (file)
 // You should have received a copy of the GNU Lesser General Public
 // License along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+#include <assert.h>
 #include <stdbool.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <string.h>
 
 #include "dec.h"
@@ -25,22 +27,26 @@ enum YACErr
 YACIterList(
     void *cbState,
     struct YACAtom *atom,
-    ptrdiff_t *off,
+    size_t *off,
     const unsigned char *buf,
     const size_t len,
     YACIterCb cb)
 {
-    struct YACErrAndLen errLen = {.err = YACErrInvalid, .len = 0};
+    size_t got = 0;
     enum YACErr err = YACErrInvalid;
     bool eoc = false;
     for (size_t n = 0;; n++) {
-        errLen = YACAtomDecode(atom, buf + *off, len - (size_t)(*off));
-        if (errLen.err != YACErrNo) {
-            return errLen.err;
+        assert(len >= (*off));
+        err = YACAtomDecode(&got, atom, buf + *off, len - (*off));
+        if (err != YACErrNo) {
+            return err;
         }
-        (*off) += errLen.len;
+        if ((SIZE_MAX - got) < (*off)) {
+            return YACErrLenTooBig;
+        }
+        (*off) += got;
         eoc = atom->typ == YACItemEOC;
-        err = cb(NULL, 0, eoc ? -1 : (ptrdiff_t)n, cbState, atom, off, buf, len);
+        err = cb(NULL, 0, !eoc, n, cbState, atom, off, buf, len);
         if (err != YACErrNo) {
             return err;
         }
@@ -55,23 +61,27 @@ enum YACErr
 YACIterMap(
     void *cbState,
     struct YACAtom *atom,
-    ptrdiff_t *off,
+    size_t *off,
     const unsigned char *buf,
     const size_t len,
     YACIterCb cb)
 {
-    struct YACErrAndLen errLen = {.err = YACErrInvalid, .len = 0};
     enum YACErr err = YACErrInvalid;
+    size_t got = 0;
     const unsigned char *key = NULL;
     size_t keyLen = 0;
     for (;;) {
-        errLen = YACAtomDecode(atom, buf + *off, len - (size_t)(*off));
-        if (errLen.err != YACErrNo) {
-            return errLen.err;
+        assert(len >= (*off));
+        err = YACAtomDecode(&got, atom, buf + *off, len - (*off));
+        if (err != YACErrNo) {
+            return err;
+        }
+        if ((SIZE_MAX - got) < (*off)) {
+            return YACErrLenTooBig;
         }
-        (*off) += errLen.len;
+        (*off) += got;
         if (atom->typ == YACItemEOC) {
-            err = cb(NULL, 0, -1, cbState, atom, off, buf, len);
+            err = cb(NULL, 0, false, 0, cbState, atom, off, buf, len);
             if (err != YACErrNo) {
                 return err;
             }
@@ -92,15 +102,19 @@ YACIterMap(
         }
         keyLen = atom->v.str.len;
         key = atom->v.str.ptr;
-        errLen = YACAtomDecode(atom, buf + *off, len - (size_t)(*off));
-        if (errLen.err != YACErrNo) {
-            return errLen.err;
+        assert(len >= (*off));
+        err = YACAtomDecode(&got, atom, buf + *off, len - (*off));
+        if (err != YACErrNo) {
+            return err;
+        }
+        if ((SIZE_MAX - got) < (*off)) {
+            return YACErrLenTooBig;
         }
-        (*off) += errLen.len;
+        (*off) += got;
         if (atom->typ == YACItemEOC) {
             return YACErrMapNoVal;
         }
-        err = cb(key, keyLen, -1, cbState, atom, off, buf, len);
+        err = cb(key, keyLen, false, 0, cbState, atom, off, buf, len);
         if (err != YACErrNo) {
             return err;
         }
@@ -112,30 +126,38 @@ enum YACErr
 YACIterBlob(
     void *cbState,
     struct YACAtom *atom,
-    ptrdiff_t *off,
+    size_t *off,
     const unsigned char *buf,
     const size_t len,
     YACIterCb cb)
 {
-    const size_t chunkLen = (size_t)(atom->v.blob.chunkLen);
-    struct YACErrAndLen errLen = {.err = YACErrInvalid, .len = 0};
+    const size_t chunkLen = atom->v.blob.chunkLen;
     enum YACErr err = YACErrInvalid;
+    size_t got = 0;
     bool eoc = false;
     for (size_t n = 0; !eoc; n++) {
-        errLen = YACAtomDecode(atom, buf + *off, len - (size_t)(*off));
-        if (errLen.err != YACErrNo) {
-            return errLen.err;
+        assert(len >= (*off));
+        err = YACAtomDecode(&got, atom, buf + *off, len - (*off));
+        if (err != YACErrNo) {
+            return err;
+        }
+        if ((SIZE_MAX - got) < (*off)) {
+            return YACErrLenTooBig;
         }
-        (*off) += errLen.len;
+        (*off) += got;
         switch (atom->typ) {
         case YACItemNIL:
-            if (((ptrdiff_t)len - *off) <= (ptrdiff_t)chunkLen) {
+            assert(len >= (*off));
+            if ((len - *off) <= chunkLen) {
                 atom->v.str.len = chunkLen;
                 return YACErrNotEnough;
             }
             atom->typ = YACItemBin;
             atom->v.str.ptr = buf + *off;
             atom->v.str.len = chunkLen;
+            if ((SIZE_MAX - chunkLen) < (*off)) {
+                return YACErrLenTooBig;
+            }
             (*off) += chunkLen;
             break;
         case YACItemBin:
@@ -144,28 +166,15 @@ YACIterBlob(
             }
             eoc = true;
             break;
-        case YACItemEOC:
-        case YACItemFalse:
-        case YACItemTrue:
-        case YACItemUUID:
-        case YACItemPint:
-        case YACItemNint:
-        case YACItemList:
-        case YACItemMap:
-        case YACItemBlob:
-        case YACItemFloat:
-        case YACItemTAI64:
-        case YACItemStr:
-        case YACItemRaw:
         default:
             return YACErrBlobBadAtom;
         }
-        err = cb(NULL, 0, (ptrdiff_t)n, cbState, atom, off, buf, len);
+        err = cb(NULL, 0, true, n, cbState, atom, off, buf, len);
         if (err != YACErrNo) {
             return err;
         }
     }
     atom->typ = YACItemEOC;
-    err = cb(NULL, 0, -1, cbState, atom, off, buf, len);
+    err = cb(NULL, 0, false, 0, cbState, atom, off, buf, len);
     return err;
 }
index a310fc5fb7b49427cdb4038443fc9c53ee3fded29a23f5fe9530c210bcab5fe7..028ae6d0bbc506dc3abfc2b86a60a492fee8bc0a87cd796db308d117e1a3e96a 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef YAC_ITER_H
 #define YAC_ITER_H
 
+#include <stdbool.h>
 #include <stddef.h>
 
 #include "dec.h"
 typedef enum YACErr (*YACIterCb)(
     const unsigned char *key,
     const size_t keyLen,
-    const ptrdiff_t idx,
+    const bool inList,
+    const size_t idx,
     void *cbState,
     struct YACAtom *atom,
-    ptrdiff_t *off,
+    size_t *off,
     const unsigned char *buf,
     const size_t len);
 
@@ -20,7 +22,7 @@ enum YACErr
 YACIterList(
     void *cbState,
     struct YACAtom *atom,
-    ptrdiff_t *off,
+    size_t *off,
     const unsigned char *buf,
     const size_t len,
     YACIterCb cb);
@@ -29,7 +31,7 @@ enum YACErr
 YACIterMap(
     void *cbState,
     struct YACAtom *atom,
-    ptrdiff_t *off,
+    size_t *off,
     const unsigned char *buf,
     const size_t len,
     YACIterCb cb);
@@ -38,7 +40,7 @@ enum YACErr
 YACIterBlob(
     void *cbState,
     struct YACAtom *atom,
-    ptrdiff_t *off,
+    size_t *off,
     const unsigned char *buf,
     const size_t len,
     YACIterCb cb);
index 9e01798547e4f2e70dd9372ae0bf65a59292e893b05045017b05065567eb35fb..3448f1afb66a79fcdb27cf9d572e4b62774a651e37bbcda61d4a1b63c313926b 100644 (file)
@@ -1,6 +1,5 @@
 #include <stddef.h>
 #include <string.h>
-#include <sys/time.h>
 
 #include "../dec.h"
 #include "../dectai.h"
@@ -12,7 +11,7 @@
 enum YACErr
 YACCerParse(
     struct YACCer *cer,
-    ptrdiff_t *off,
+    size_t *off,
     char **failReason,
     const unsigned char *buf,
     const size_t len)
@@ -23,20 +22,20 @@ YACCerParse(
     if (err != YACErrNo) {
         return err;
     }
-    ptrdiff_t idx = 0;
+    size_t idx = 0;
     struct YACItem *item = NULL;
-    if (YACItemsGetByKey(items, 0, "hash") != -1) {
+    if (YACItemsGetByKey(items, 0, "hash") != 0) {
         (*failReason) = "unexpected /hash";
         return YACErrUnsatisfiedSchema;
     }
-    ptrdiff_t loadIdx = YACItemsGetByKey(items, 0, "load");
+    size_t loadIdx = YACItemsGetByKey(items, 0, "load");
     {
-        if (loadIdx == -1) {
+        if (loadIdx == 0) {
             (*failReason) = "no /load";
             return YACErrUnsatisfiedSchema;
         }
         idx = YACItemsGetByKeyAndType(items, loadIdx, "t", YACItemStr);
-        if (loadIdx == -1) {
+        if (loadIdx == 0) {
             (*failReason) = "no /load/t";
             return YACErrUnsatisfiedSchema;
         }
@@ -47,12 +46,12 @@ YACCerParse(
     }
     cer->load = YACItemsGetByKey(items, loadIdx, "v");
     {
-        if (cer->load == -1) {
+        if (cer->load == 0) {
             (*failReason) = "no /load/v";
             return YACErrUnsatisfiedSchema;
         }
         idx = YACItemsGetByKey(items, cer->load, "ku");
-        if (idx != -1) {
+        if (idx != 0) {
             item = &(items->list[idx]);
             if (item->atom.v.list.len == 0) {
                 (*failReason) = "empty /load/v/ku";
@@ -66,7 +65,7 @@ YACCerParse(
     }
     idx = YACItemsGetByKey(items, cer->load, "pub");
     {
-        if (idx == -1) {
+        if (idx == 0) {
             (*failReason) = "no /load/v/pub";
             return YACErrUnsatisfiedSchema;
         }
@@ -77,19 +76,18 @@ YACCerParse(
         }
         idx = items->list[idx].atom.v.list.head;
         cer->pub = idx;
-        while (idx != -1) {
-            if (YACItemsGetByKeyAndType(items, idx, "a", YACItemStr) == -1) {
+        while (idx != 0) {
+            if (YACItemsGetByKeyAndType(items, idx, "a", YACItemStr) == 0) {
                 (*failReason) = "no /load/v/pub/a";
                 return YACErrUnsatisfiedSchema;
             }
-            if (YACItemsGetByKeyAndType(items, idx, "v", YACItemBin) == -1) {
+            if (YACItemsGetByKeyAndType(items, idx, "v", YACItemBin) == 0) {
                 (*failReason) = "no /load/v/pub/v";
                 return YACErrUnsatisfiedSchema;
             }
             {
-                ptrdiff_t pkidIdx =
-                    YACItemsGetByKeyAndType(items, idx, "id", YACItemUUID);
-                if (pkidIdx == -1) {
+                size_t pkidIdx = YACItemsGetByKeyAndType(items, idx, "id", YACItemUUID);
+                if (pkidIdx == 0) {
                     (*failReason) = "no /load/v/pub/id";
                     return YACErrUnsatisfiedSchema;
                 }
@@ -100,7 +98,7 @@ YACCerParse(
     }
     cer->sub = YACItemsGetByKey(items, cer->load, "sub");
     {
-        if (cer->sub == -1) {
+        if (cer->sub == 0) {
             (*failReason) = "no /load/v/sub";
             return YACErrUnsatisfiedSchema;
         }
@@ -114,13 +112,13 @@ YACCerParse(
             return YACErrUnsatisfiedSchema;
         }
     }
-    if (YACItemsGetByKey(items, cer->load, "crit") != -1) {
+    if (YACItemsGetByKey(items, cer->load, "crit") != 0) {
         (*failReason) = "/load/v/crit is unsupported";
         return YACErrUnsatisfiedSchema;
     }
-    ptrdiff_t sigsIdx = YACItemsGetByKey(items, 0, "sigs");
+    size_t sigsIdx = YACItemsGetByKey(items, 0, "sigs");
     {
-        if (sigsIdx == -1) {
+        if (sigsIdx == 0) {
             (*failReason) = "no /sigs";
             return YACErrUnsatisfiedSchema;
         }
@@ -129,54 +127,54 @@ YACCerParse(
             (*failReason) = "len(/load/sigs) != 1";
             return YACErrUnsatisfiedSchema;
         }
-        ptrdiff_t sigIdx = items->list[sigsIdx].atom.v.list.head;
+        size_t sigIdx = items->list[sigsIdx].atom.v.list.head;
         cer->sig = sigIdx;
-        while (sigIdx != -1) {
-            if (YACItemsGetByKey(items, sigIdx, "hash") != -1) {
+        while (sigIdx != 0) {
+            if (YACItemsGetByKey(items, sigIdx, "hash") != 0) {
                 (*failReason) = "unexpected /sigs/./hash met";
                 return YACErrUnsatisfiedSchema;
             }
             {
                 idx = YACItemsGetByKey(items, sigIdx, "sign");
-                if (idx == -1) {
+                if (idx == 0) {
                     (*failReason) = "no /sigs/./sign";
                     return YACErrUnsatisfiedSchema;
                 }
-                if (YACItemsGetByKeyAndType(items, idx, "a", YACItemStr) == -1) {
+                if (YACItemsGetByKeyAndType(items, idx, "a", YACItemStr) == 0) {
                     (*failReason) = "no /sigs/./sign/a";
                     return YACErrUnsatisfiedSchema;
                 }
-                if (YACItemsGetByKeyAndType(items, idx, "v", YACItemBin) == -1) {
+                if (YACItemsGetByKeyAndType(items, idx, "v", YACItemBin) == 0) {
                     (*failReason) = "no /sigs/./sign/v";
                     return YACErrUnsatisfiedSchema;
                 }
             }
             {
                 idx = YACItemsGetByKey(items, sigIdx, "tbs");
-                if (idx == -1) {
+                if (idx == 0) {
                     (*failReason) = "no /sigs/./tbs";
                     return YACErrUnsatisfiedSchema;
                 }
                 {
-                    ptrdiff_t cidIdx =
+                    size_t cidIdx =
                         YACItemsGetByKeyAndType(items, idx, "cid", YACItemUUID);
-                    if (cidIdx == -1) {
+                    if (cidIdx == 0) {
                         (*failReason) = "no /sigs/./tbs/cid";
                         return YACErrUnsatisfiedSchema;
                     }
                     cer->cid = items->list[cidIdx].atom.v.uuid;
                 }
                 {
-                    ptrdiff_t sidIdx =
+                    size_t sidIdx =
                         YACItemsGetByKeyAndType(items, idx, "sid", YACItemUUID);
-                    if (sidIdx == -1) {
+                    if (sidIdx == 0) {
                         (*failReason) = "no /sigs/./tbs/sid";
                         return YACErrUnsatisfiedSchema;
                     }
                     cer->sid = items->list[sidIdx].atom.v.uuid;
                 }
                 idx = YACItemsGetByKeyAndType(items, idx, "exp", YACItemList);
-                if (idx == -1) {
+                if (idx == 0) {
                     (*failReason) = "no /sigs/./tbs/exp";
                     return YACErrUnsatisfiedSchema;
                 }
@@ -189,19 +187,19 @@ YACCerParse(
                     (*failReason) = "len(/sigs/./tbs/exp) != 2";
                     return YACErrUnsatisfiedSchema;
                 }
-                err = YACTAI64ToTimeval(
+                err = YACTAI64ToTimespec(
                     &(cer->since),
                     items->list[idx + 1].atom.v.str.ptr,
                     items->list[idx + 1].atom.v.str.len);
-                if ((err != YACErrNo) || (cer->since.tv_usec != 0)) {
+                if ((err != YACErrNo) || (cer->since.tv_nsec != 0)) {
                     (*failReason) = "bad /sigs/./tbs/exp/since value";
                     return YACErrUnsatisfiedSchema;
                 }
-                err = YACTAI64ToTimeval(
+                err = YACTAI64ToTimespec(
                     &(cer->till),
                     items->list[idx + 2].atom.v.str.ptr,
                     items->list[idx + 2].atom.v.str.len);
-                if ((err != YACErrNo) || (cer->till.tv_usec != 0)) {
+                if ((err != YACErrNo) || (cer->till.tv_nsec != 0)) {
                     (*failReason) = "bad /sigs/./tbs/exp/till value";
                     return YACErrUnsatisfiedSchema;
                 }
@@ -219,7 +217,7 @@ YACCerVerify(
     struct YACCer *cer,
     struct YACCer *pool,
     const size_t poolLen,
-    struct YACCerVerifyOpts opts)
+    const struct YACCerVerifyOpts opts)
 {
     if (opts.t.tv_sec <= cer->since.tv_sec) {
         (*failReason) = "unsatisfied since";
@@ -244,7 +242,7 @@ YACCerVerify(
         &((*verifier)->items), (*verifier)->pub, "a")]);
     struct YACItem *pubV = &((*verifier)->items.list[YACItemsGetByKey(
         &((*verifier)->items), (*verifier)->pub, "v")]);
-    ptrdiff_t signIdx = YACItemsGetByKey(&(cer->items), cer->sig, "sign");
+    size_t signIdx = YACItemsGetByKey(&(cer->items), cer->sig, "sign");
     struct YACItem *sigV =
         &(cer->items.list[YACItemsGetByKey(&(cer->items), signIdx, "v")]);
     {
@@ -259,7 +257,7 @@ YACCerVerify(
     }
     const size_t cap = 1 << 10;
     unsigned char buf[1 << 10] = {0};
-    ptrdiff_t off = 0;
+    size_t off = 0;
     {
         const size_t items = 5;
         struct YACItem tbsItems[5];
@@ -284,43 +282,43 @@ YACCerVerify(
         tbsItems[3].next = 4;
 
         tbsItems[4].atom.typ = YACItemNIL;
-        tbsItems[4].next = -1;
+        tbsItems[4].next = 0;
 
-        if (YACItemsEncode(&tbs, 0, &off, buf, cap) != 0) {
-            (*failReason) = "can not prepare tbs";
+        if (!YACItemsEncode(&tbs, 0, &off, buf, cap)) {
+            (*failReason) = "can not prepare tbs: start";
             return false;
         }
     }
     off -= 2; // strip off NIL and EOC, continue map generation
-    if (YACItemsEncode(&(cer->items), cer->load, &off, buf, cap) != 0) {
-        (*failReason) = "can not prepare tbs";
+    if (!YACItemsEncode(&(cer->items), cer->load, &off, buf, cap)) {
+        (*failReason) = "can not prepare tbs: load";
         return false;
     }
     {
-        ptrdiff_t diff = YACAtomStrEncode(
-            buf + off, cap - (size_t)off, (const unsigned char *)"tbs", 3);
-        if (diff < 1) {
-            (*failReason) = "can not prepare tbs";
+        size_t got = 0;
+        if (!YACAtomStrEncode(
+                &got, buf + off, cap - off, (const unsigned char *)"tbs", 3)) {
+            (*failReason) = "can not prepare tbs: tbs key";
             return false;
         }
-        off += diff;
+        off += got;
     }
-    if (YACItemsEncode(
+    if (!YACItemsEncode(
             &(cer->items),
             YACItemsGetByKey(&(cer->items), cer->sig, "tbs"),
             &off,
             buf,
-            cap) != 0) {
-        (*failReason) = "can not prepare tbs";
+            cap)) {
+        (*failReason) = "can not prepare tbs: tbs";
         return false;
     }
     {
-        ptrdiff_t diff = YACAtomEOCEncode(buf + off, cap - (size_t)off);
-        if (diff < 1) {
-            (*failReason) = "can not prepare tbs";
+        size_t got = 0;
+        if (!YACAtomEOCEncode(&got, buf + off, cap - off)) {
+            (*failReason) = "can not prepare tbs: eoc";
             return false;
         }
-        off += diff;
+        off += got;
     }
     for (size_t i = 0; i < opts.sigVerifiersLen; i++) {
         if (!YACStrEqual(&(pubA->atom), opts.sigVerifiers[i].algo)) {
@@ -335,7 +333,7 @@ YACCerVerify(
             pubV->atom.v.str.ptr,
             pubV->atom.v.str.len,
             buf,
-            (size_t)off);
+            off);
     }
     (*failReason) = "no signature verifier found";
     return false;
index 052a0ab0ce859a7282086ad3ff843ae0f80673744b37ac913a60a9941235b38f..e72b70906f65f745f5a3bd31490ea397a34e0dda88859800856e45b102a91dcd 100644 (file)
@@ -3,28 +3,28 @@
 
 #include <stdbool.h>
 #include <stddef.h>
-#include <sys/time.h>
+#include <time.h>
 
 #include "../err.h"
 #include "../items.h"
 
 struct YACCer {
     struct YACItems items;
-    ptrdiff_t load;
-    ptrdiff_t pub;
-    ptrdiff_t sub;
-    ptrdiff_t sig;
+    size_t load;
+    size_t pub;
+    size_t sub;
+    size_t sig;
     const unsigned char *cid;
     const unsigned char *pkid;
     const unsigned char *sid;
-    struct timeval since;
-    struct timeval till;
+    struct timespec since;
+    struct timespec till;
 };
 
 enum YACErr
 YACCerParse(
     struct YACCer *,
-    ptrdiff_t *off,
+    size_t *off,
     char **failReason,
     const unsigned char *buf,
     const size_t len);
@@ -46,7 +46,7 @@ struct YACCerSigVerifier {
 };
 
 struct YACCerVerifyOpts {
-    struct timeval t;
+    struct timespec t;
     struct YACCerSigVerifier *sigVerifiers;
     size_t sigVerifiersLen;
 };
@@ -58,6 +58,6 @@ YACCerVerify(
     struct YACCer *cer,
     struct YACCer *pool,
     const size_t poolLen,
-    struct YACCerVerifyOpts opts);
+    const struct YACCerVerifyOpts opts);
 
 #endif // YAC_CER_H
diff --git a/cyac/lint/.clang-format b/cyac/lint/.clang-format
new file mode 100644 (file)
index 0000000..c199ca8
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    BasedOnStyle: llvm,
+    ColumnLimit: 88,
+    IndentWidth: 4,
+    AlignAfterOpenBracket: AlwaysBreak,
+    AlignConsecutiveAssignments: false,
+    AllowAllParametersOfDeclarationOnNextLine: false,
+    AllowShortBlocksOnASingleLine: true,
+    AlwaysBreakAfterReturnType: TopLevel,
+    BinPackArguments: false,
+    BinPackParameters: false,
+    BreakBeforeTernaryOperators: false,
+    BreakStringLiterals: false,
+    BreakBeforeBraces: Custom,
+    BraceWrapping: {
+        AfterFunction: true,
+    },
+}
diff --git a/cyac/lint/iwyu-maps.imp b/cyac/lint/iwyu-maps.imp
new file mode 100644 (file)
index 0000000..446e7e9
--- /dev/null
@@ -0,0 +1,5 @@
+[
+    { symbol: ["CLOCK_REALTIME", "private", "<time.h>", "public"] },
+    { symbol: ["PTRDIFF_MAX", "private", "<stdint.h>", "public"] },
+    { symbol: ["SIZE_MAX", "private", "<stdint.h>", "public"] },
+]
index 5bc7a92fafb489f28eeb9cf62b7d92749c2dd7fa821384e0c8e199ddc66ed0dd..459b7c4026d6f4b39e4df967541345f94db8f49b942dadaee8908f8b1fd45767 100644 (file)
@@ -65,23 +65,22 @@ func (raw *Raw) String() string {
 }
 
 var (
-       ErrNotEnough      = errors.New("not enough data")
-       ErrLenNonMinimal  = errors.New("non-minimal len")
-       ErrLenTooBig      = errors.New("string len >1<<60")
-       ErrIntZeroByte    = errors.New("zero byte int")
-       ErrUnknownType    = errors.New("unknown type")
-       ErrBadUTF8        = errors.New("invalid UTF-8")
-       ErrMapBadKey      = errors.New("map bad key")
-       ErrMapUnordered   = errors.New("map unordered")
-       ErrMapBadVal      = errors.New("map no value")
-       ErrBlobBadLen     = errors.New("bad blob len")
-       ErrBlobBadAtom    = errors.New("blob unexpected atom")
-       ErrBlobShortChunk = errors.New("blob short chunk")
-       ErrBlobBadTerm    = errors.New("blob bad terminator")
+       ErrNotEnough     = errors.New("not enough data")
+       ErrLenNonMinimal = errors.New("non-minimal len")
+       ErrLenTooBig     = errors.New("string len >1<<60")
+       ErrIntNonMinimal = errors.New("int non minimal")
+       ErrUnknownType   = errors.New("unknown type")
+       ErrBadUTF8       = errors.New("invalid UTF-8")
+       ErrMapBadKey     = errors.New("map bad key")
+       ErrMapUnordered  = errors.New("map unordered")
+       ErrMapNoVal      = errors.New("map no value")
+       ErrBlobBadLen    = errors.New("blob bad len")
+       ErrBlobBadAtom   = errors.New("blob unexpected atom")
+       ErrBlobBadTerm   = errors.New("blob bad terminator")
 )
 
 func AtomDecode(buf []byte) (item *Item, off int, err error) {
-       off++
+       off = 1
        if len(buf) < 1 {
                err = ErrNotEnough
                return
@@ -110,7 +109,7 @@ func AtomDecode(buf []byte) (item *Item, off int, err error) {
                                return
                        }
                        ul := FromBE(buf[1 : 1+ll])
-                       if ul > (1 << 60) {
+                       if ul > (1 << 63) {
                                err = ErrLenTooBig
                                return
                        }
@@ -121,6 +120,10 @@ func AtomDecode(buf []byte) (item *Item, off int, err error) {
                        }
                }
                off += l
+               if off <= 0 {
+                       err = ErrLenTooBig
+                       return
+               }
                if len(buf) < off {
                        err = ErrNotEnough
                        return
@@ -163,7 +166,7 @@ func AtomDecode(buf []byte) (item *Item, off int, err error) {
                        return
                }
                if buf[1] == 0 {
-                       err = ErrIntZeroByte
+                       err = ErrIntNonMinimal
                        return
                }
                if l > 8 {
@@ -173,13 +176,18 @@ func AtomDecode(buf []byte) (item *Item, off int, err error) {
                }
                v := FromBE(buf[1 : 1+l])
                if v < 32 {
-                       err = ErrLenNonMinimal
+                       err = ErrIntNonMinimal
                        return
                }
                if item.Typ() == ItemUInt {
                        item.V = v
                } else {
-                       item.V = -1 - int64(v)
+                       if v >= (1 << 63) {
+                               item.T = byte(ItemRaw)
+                               item.V = &Raw{T: AtomType(buf[0]), V: buf[1 : 1+l]}
+                       } else {
+                               item.V = -1 - int64(v)
+                       }
                }
                return
        }
@@ -219,7 +227,7 @@ func AtomDecode(buf []byte) (item *Item, off int, err error) {
                        err = ErrBlobBadLen
                        return
                }
-               if chunkLen > (1 << 60) {
+               if chunkLen >= (1 << 63) {
                        err = ErrLenTooBig
                        return
                }
@@ -353,7 +361,7 @@ func DecodeItem(buf []byte) (item *Item, tail []byte, err error) {
                                return
                        }
                        if sub.T == byte(ItemEOC) {
-                               err = ErrMapBadVal
+                               err = ErrMapNoVal
                                return
                        }
                        v[keyPrev] = sub
@@ -374,7 +382,7 @@ func DecodeItem(buf []byte) (item *Item, tail []byte, err error) {
                        switch sub.T {
                        case byte(ItemNIL):
                                if len(buf) <= chunkLen {
-                                       err = ErrBlobShortChunk
+                                       err = ErrNotEnough
                                        return
                                }
                                v.Chunks = append(v.Chunks, buf[:chunkLen])