mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-07 10:20:29 +00:00
Merge remote-tracking branch 'upstream/master' into bugfix_typos
This commit is contained in:
commit
6c013d7b86
48 changed files with 696 additions and 750 deletions
Binary file not shown.
|
@ -39,15 +39,17 @@
|
||||||
* @param l is byte length of `s`
|
* @param l is byte length of `s`
|
||||||
* @return bytes appended (always `l`) or -1 if `ENOMEM`
|
* @return bytes appended (always `l`) or -1 if `ENOMEM`
|
||||||
* @see appendz(b).i to get buffer length
|
* @see appendz(b).i to get buffer length
|
||||||
|
* @note 20% faster than appends()
|
||||||
*/
|
*/
|
||||||
ssize_t appendd(char **b, const void *s, size_t l) {
|
ssize_t appendd(char **b, const void *s, size_t l) {
|
||||||
char *p;
|
char *p;
|
||||||
|
size_t n;
|
||||||
struct appendz z;
|
struct appendz z;
|
||||||
assert(b);
|
|
||||||
z = appendz((p = *b));
|
z = appendz((p = *b));
|
||||||
if (ROUNDUP(z.i + l + 1, 8) + W > z.n) {
|
n = ROUNDUP(z.i + l + 1, 8) + W;
|
||||||
|
if (n > z.n) {
|
||||||
if (!z.n) z.n = W * 2;
|
if (!z.n) z.n = W * 2;
|
||||||
while (ROUNDUP(z.i + l + 1, 8) + W > z.n) z.n += z.n >> 1;
|
while (n > z.n) z.n += z.n >> 1;
|
||||||
z.n = ROUNDUP(z.n, W);
|
z.n = ROUNDUP(z.n, W);
|
||||||
if ((p = realloc(p, z.n))) {
|
if ((p = realloc(p, z.n))) {
|
||||||
z.n = malloc_usable_size(p);
|
z.n = malloc_usable_size(p);
|
||||||
|
@ -59,9 +61,7 @@ ssize_t appendd(char **b, const void *s, size_t l) {
|
||||||
}
|
}
|
||||||
*(char *)mempcpy(p + z.i, s, l) = 0;
|
*(char *)mempcpy(p + z.i, s, l) = 0;
|
||||||
z.i += l;
|
z.i += l;
|
||||||
if (!IsTiny() && W == 8) {
|
if (!IsTiny() && W == 8) z.i |= (size_t)APPEND_COOKIE << 48;
|
||||||
z.i |= (size_t)APPEND_COOKIE << 48;
|
|
||||||
}
|
|
||||||
*(size_t *)(p + z.n - W) = z.i;
|
*(size_t *)(p + z.n - W) = z.i;
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
*
|
*
|
||||||
* @return bytes appended or -1 if `ENOMEM`
|
* @return bytes appended or -1 if `ENOMEM`
|
||||||
* @see appendz(b).i to get buffer length
|
* @see appendz(b).i to get buffer length
|
||||||
|
* @note O(1) amortized buffer growth
|
||||||
*/
|
*/
|
||||||
ssize_t(appendf)(char **b, const char *fmt, ...) {
|
ssize_t(appendf)(char **b, const char *fmt, ...) {
|
||||||
int n;
|
int n;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/nexgen32e/bsr.h"
|
||||||
#include "libc/stdio/append.internal.h"
|
#include "libc/stdio/append.internal.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
|
@ -37,35 +38,39 @@
|
||||||
* free(b);
|
* free(b);
|
||||||
*
|
*
|
||||||
* If `i` is greater than the current length then the extra bytes are
|
* If `i` is greater than the current length then the extra bytes are
|
||||||
* filled with NUL characters.
|
* filled with NUL characters. If `i` is less than the current length
|
||||||
|
* then memory is released to the system.
|
||||||
*
|
*
|
||||||
* The resulting buffer is guaranteed to be NUL-terminated, i.e.
|
* The resulting buffer is guaranteed to be NUL-terminated, i.e.
|
||||||
* `!b[appendz(b).i]` will be the case.
|
* `!b[appendz(b).i]` will be the case even if both params are 0.
|
||||||
*
|
*
|
||||||
* @return `i` or -1 if `ENOMEM`
|
* @return `i` or -1 if `ENOMEM`
|
||||||
* @see appendz(b).i to get buffer length
|
* @see appendz(b).i to get buffer length
|
||||||
*/
|
*/
|
||||||
ssize_t appendr(char **b, size_t i) {
|
ssize_t appendr(char **b, size_t i) {
|
||||||
char *p;
|
char *p;
|
||||||
|
size_t n;
|
||||||
struct appendz z;
|
struct appendz z;
|
||||||
assert(b);
|
assert(b);
|
||||||
z = appendz((p = *b));
|
z = appendz((p = *b));
|
||||||
z.n = ROUNDUP(i + 1, 8) + W;
|
if (i != z.i || !p) {
|
||||||
if ((p = realloc(p, z.n))) {
|
n = ROUNDUP(i + 1, 8) + W;
|
||||||
z.n = malloc_usable_size(p);
|
if (n > z.n || bsrl(n) < bsrl(z.n)) {
|
||||||
assert(!(z.n & (W - 1)));
|
if ((p = realloc(p, n))) {
|
||||||
|
n = malloc_usable_size(p);
|
||||||
|
assert(!(n & (W - 1)));
|
||||||
*b = p;
|
*b = p;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (i > z.i) {
|
if (i > z.i) {
|
||||||
memset(p, z.i, i - z.i);
|
memset(p + z.i, 0, i - z.i + 1);
|
||||||
|
} else {
|
||||||
|
p[i] = 0;
|
||||||
}
|
}
|
||||||
z.i = i;
|
*(size_t *)(p + n - W) =
|
||||||
p[z.i] = 0;
|
i | (!IsTiny() && W == 8 ? (size_t)APPEND_COOKIE << 48 : 0);
|
||||||
if (!IsTiny() && W == 8) {
|
|
||||||
z.i |= (size_t)APPEND_COOKIE << 48;
|
|
||||||
}
|
}
|
||||||
*(size_t *)(p + z.n - W) = z.i;
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
*
|
*
|
||||||
* @return bytes appended (always `strlen(s)`) or -1 if `ENOMEM`
|
* @return bytes appended (always `strlen(s)`) or -1 if `ENOMEM`
|
||||||
* @see appendz(b).i to get buffer length
|
* @see appendz(b).i to get buffer length
|
||||||
|
* @note 2x faster than appendf()
|
||||||
*/
|
*/
|
||||||
ssize_t appends(char **b, const char *s) {
|
ssize_t appends(char **b, const char *s) {
|
||||||
return appendd(b, s, strlen(s));
|
return appendd(b, s, strlen(s));
|
||||||
|
|
|
@ -16,18 +16,23 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/assert.h"
|
||||||
#include "libc/bits/bits.h"
|
#include "libc/bits/bits.h"
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/nexgen32e/bsr.h"
|
#include "libc/nexgen32e/bsr.h"
|
||||||
#include "libc/stdio/append.internal.h"
|
#include "libc/stdio/append.internal.h"
|
||||||
|
|
||||||
|
#define W sizeof(size_t)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends character or word-encoded string to buffer.
|
* Appends character or word-encoded string to buffer.
|
||||||
*
|
*
|
||||||
* Up to eight characters can be appended. For example:
|
* Up to eight characters can be appended. For example:
|
||||||
*
|
*
|
||||||
* appendw(&s, 'h'|'i'<<8);
|
* appendw(&s, 'h'|'i'<<8);
|
||||||
|
* appendw(&s, READ64LE("hi\0\0\0\0\0"));
|
||||||
*
|
*
|
||||||
* Is equivalent to:
|
* Are equivalent to:
|
||||||
*
|
*
|
||||||
* appends(&s, "hi");
|
* appends(&s, "hi");
|
||||||
*
|
*
|
||||||
|
@ -37,15 +42,40 @@
|
||||||
*
|
*
|
||||||
* Will append a single NUL character.
|
* Will append a single NUL character.
|
||||||
*
|
*
|
||||||
|
* This function is slightly faster than appendd() and appends(). Its
|
||||||
|
* main advantage is it improves code size in functions that call it.
|
||||||
|
*
|
||||||
* The resulting buffer is guaranteed to be NUL-terminated, i.e.
|
* The resulting buffer is guaranteed to be NUL-terminated, i.e.
|
||||||
* `!b[appendz(b).i]` will be the case.
|
* `!b[appendz(b).i]` will be the case.
|
||||||
*
|
*
|
||||||
* @return bytes appended or -1 if `ENOMEM`
|
* @return bytes appended or -1 if `ENOMEM`
|
||||||
|
* @see appendz(b).i to get buffer length
|
||||||
*/
|
*/
|
||||||
ssize_t appendw(char **b, uint64_t w) {
|
ssize_t appendw(char **b, uint64_t w) {
|
||||||
char t[8];
|
size_t n;
|
||||||
unsigned n = 1;
|
unsigned l;
|
||||||
WRITE64LE(t, w);
|
char *p, *q;
|
||||||
if (w) n += bsrl(w) >> 3;
|
struct appendz z;
|
||||||
return appendd(b, t, n);
|
z = appendz((p = *b));
|
||||||
|
l = w ? (bsrl(w) >> 3) + 1 : 1;
|
||||||
|
n = ROUNDUP(z.i + 8 + 1, 8) + W;
|
||||||
|
if (n > z.n) {
|
||||||
|
if (!z.n) z.n = W * 2;
|
||||||
|
while (n > z.n) z.n += z.n >> 1;
|
||||||
|
z.n = ROUNDUP(z.n, W);
|
||||||
|
if ((p = realloc(p, z.n))) {
|
||||||
|
z.n = malloc_usable_size(p);
|
||||||
|
assert(!(z.n & (W - 1)));
|
||||||
|
*b = p;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
q = p + z.i;
|
||||||
|
WRITE64LE(q, w);
|
||||||
|
q[8] = 0;
|
||||||
|
z.i += l;
|
||||||
|
if (!IsTiny() && W == 8) z.i |= (size_t)APPEND_COOKIE << 48;
|
||||||
|
*(size_t *)(p + z.n - W) = z.i;
|
||||||
|
return l;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
/**
|
/**
|
||||||
* Returns size of append buffer.
|
* Returns size of append buffer.
|
||||||
*
|
*
|
||||||
|
* @param p must be 0 or have been allocated by an append*() function
|
||||||
* @return i is number of bytes stored in buffer
|
* @return i is number of bytes stored in buffer
|
||||||
* @return n is number of bytes in allocation
|
* @return n is number of bytes in allocation
|
||||||
*/
|
*/
|
||||||
|
@ -36,6 +37,12 @@ struct appendz appendz(char *p) {
|
||||||
assert(z.n >= W * 2 && !(z.n & (W - 1)));
|
assert(z.n >= W * 2 && !(z.n & (W - 1)));
|
||||||
z.i = *(size_t *)(p + z.n - W);
|
z.i = *(size_t *)(p + z.n - W);
|
||||||
if (!IsTiny() && W == 8) {
|
if (!IsTiny() && W == 8) {
|
||||||
|
/*
|
||||||
|
* This check should fail if an append*() function was passed a
|
||||||
|
* pointer that was allocated manually by malloc(). Append ptrs
|
||||||
|
* can be free()'d safely, but they need to be allocated by the
|
||||||
|
* append library, because we write a special value to the end.
|
||||||
|
*/
|
||||||
assert((z.i >> 48) == APPEND_COOKIE);
|
assert((z.i >> 48) == APPEND_COOKIE);
|
||||||
z.i &= 0x0000ffffffffffff;
|
z.i &= 0x0000ffffffffffff;
|
||||||
}
|
}
|
||||||
|
|
52
libc/stdio/dumphexc.c
Normal file
52
libc/stdio/dumphexc.c
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
|
#include "libc/stdio/append.internal.h"
|
||||||
|
#include "libc/stdio/hex.internal.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns data into "\x00..." string literal.
|
||||||
|
*/
|
||||||
|
char *DumpHexc(const char *p, size_t n, size_t *z) {
|
||||||
|
long o;
|
||||||
|
int i, m;
|
||||||
|
char A[128], *q, *s = 0;
|
||||||
|
if (n == -1) n = p ? strlen(p) : 0;
|
||||||
|
appendw(&s, '"' | '\\' << 8 | '\n' << 16);
|
||||||
|
for (o = 0; (m = MIN(16, n)); p += m, n -= m) {
|
||||||
|
q = A;
|
||||||
|
for (i = 0; i < m; ++i) {
|
||||||
|
*q++ = '\\';
|
||||||
|
*q++ = 'x';
|
||||||
|
*q++ = "0123456789abcdef"[(p[i] & 0xF0) >> 4];
|
||||||
|
*q++ = "0123456789abcdef"[(p[i] & 0x0F) >> 0];
|
||||||
|
}
|
||||||
|
if (o) appendw(&s, '\\' | '\n' << 8);
|
||||||
|
appendd(&s, A, q - A);
|
||||||
|
o += m;
|
||||||
|
}
|
||||||
|
if (appendw(&s, '"') != -1) {
|
||||||
|
if (z) *z = appendz(s).i;
|
||||||
|
return s;
|
||||||
|
} else {
|
||||||
|
free(s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
11
libc/stdio/hex.internal.h
Normal file
11
libc/stdio/hex.internal.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef COSMOPOLITAN_LIBC_STDIO_HEX_INTERNAL_H_
|
||||||
|
#define COSMOPOLITAN_LIBC_STDIO_HEX_INTERNAL_H_
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
char *DumpHex(const char *, size_t, size_t *);
|
||||||
|
char *DumpHexc(const char *, size_t, size_t *);
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_LIBC_STDIO_HEX_INTERNAL_H_ */
|
|
@ -57,7 +57,7 @@ o/$(MODE)/libc/stdio/fputc.o: \
|
||||||
|
|
||||||
o//libc/stdio/appendw.o: \
|
o//libc/stdio/appendw.o: \
|
||||||
OVERRIDE_CFLAGS += \
|
OVERRIDE_CFLAGS += \
|
||||||
-O2
|
-Os
|
||||||
|
|
||||||
LIBC_STDIO_LIBS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)))
|
LIBC_STDIO_LIBS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)))
|
||||||
LIBC_STDIO_SRCS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_SRCS))
|
LIBC_STDIO_SRCS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_SRCS))
|
||||||
|
|
|
@ -30,14 +30,16 @@
|
||||||
ssize_t(vappendf)(char **b, const char *f, va_list v) {
|
ssize_t(vappendf)(char **b, const char *f, va_list v) {
|
||||||
char *p;
|
char *p;
|
||||||
int r, s;
|
int r, s;
|
||||||
|
size_t n;
|
||||||
va_list w;
|
va_list w;
|
||||||
struct appendz z;
|
struct appendz z;
|
||||||
z = appendz((p = *b));
|
z = appendz((p = *b));
|
||||||
va_copy(w, v);
|
va_copy(w, v);
|
||||||
if ((r = (vsnprintf)(p + z.i, z.n ? z.n - W - z.i : 0, f, v)) >= 0) {
|
if ((r = (vsnprintf)(p + z.i, z.n ? z.n - W - z.i : 0, f, v)) >= 0) {
|
||||||
if (ROUNDUP(z.i + r + 1, 8) + W > z.n) {
|
n = ROUNDUP(z.i + r + 1, 8) + W;
|
||||||
|
if (n > z.n) {
|
||||||
if (!z.n) z.n = W * 2;
|
if (!z.n) z.n = W * 2;
|
||||||
while (ROUNDUP(z.i + r + 1, 8) + W > z.n) z.n += z.n >> 1;
|
while (n > z.n) z.n += z.n >> 1;
|
||||||
z.n = ROUNDUP(z.n, W);
|
z.n = ROUNDUP(z.n, W);
|
||||||
if ((p = realloc(p, z.n))) {
|
if ((p = realloc(p, z.n))) {
|
||||||
z.n = malloc_usable_size(p);
|
z.n = malloc_usable_size(p);
|
||||||
|
|
|
@ -1,25 +1,26 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_BENCH_H_
|
#ifndef COSMOPOLITAN_LIBC_BENCH_H_
|
||||||
#define COSMOPOLITAN_LIBC_BENCH_H_
|
#define COSMOPOLITAN_LIBC_BENCH_H_
|
||||||
|
#include "libc/bits/safemacros.internal.h"
|
||||||
#include "libc/nexgen32e/bench.h"
|
#include "libc/nexgen32e/bench.h"
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fileoverview Microbenchmarking tools.
|
* @fileoverview Microbenchmarking Toolz.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BENCHLOOP
|
#ifndef BENCHLOOP
|
||||||
#define BENCHLOOP(START, STOP, N, INIT, EXPR) \
|
#define BENCHLOOP(START, STOP, N, INIT, EXPR) \
|
||||||
({ \
|
({ \
|
||||||
unsigned long Iter, Count; \
|
unsigned long Iter, Count; \
|
||||||
double Average, Sample, Time1, Time2; \
|
uint64_t Time1, Time2; \
|
||||||
|
double Average; \
|
||||||
for (Average = 1, Iter = 1, Count = (N); Iter < Count; ++Iter) { \
|
for (Average = 1, Iter = 1, Count = (N); Iter < Count; ++Iter) { \
|
||||||
INIT; \
|
INIT; \
|
||||||
Time1 = START(); \
|
Time1 = START(); \
|
||||||
EXPR; \
|
EXPR; \
|
||||||
Time2 = STOP(); \
|
Time2 = STOP(); \
|
||||||
Sample = Time2 - Time1; \
|
Average += 1. / Iter * (unsignedsubtract(Time2, Time1) - Average); \
|
||||||
Average += 1. / Iter * (Sample - Average); \
|
|
||||||
} \
|
} \
|
||||||
Average; \
|
Average; \
|
||||||
})
|
})
|
||||||
|
|
34
test/libc/stdio/dumphexc_test.c
Normal file
34
test/libc/stdio/dumphexc_test.c
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/stdio/hex.internal.h"
|
||||||
|
#include "libc/testlib/ezbench.h"
|
||||||
|
#include "libc/testlib/hyperion.h"
|
||||||
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
|
TEST(DumpHexc, test) {
|
||||||
|
EXPECT_STREQ("\"\\\n\
|
||||||
|
\\x68\\x65\\x6c\\x6c\\x6f\\xe2\\x86\\x92\\x0a\\x01\\x02\\x74\\x68\\x65\\x65\\x72\\\n\
|
||||||
|
\\x68\\x75\\x72\\x63\\x65\\x6f\\x61\\x68\\x72\\x63\\x75\\x6f\\x65\\x61\\x75\\x68\\\n\
|
||||||
|
\\x63\\x72\"",
|
||||||
|
DumpHexc("hello→\n\1\2theerhurceoahrcuoeauhcr", -1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCH(DumpHexc, bench) {
|
||||||
|
EZBENCH2("dumphexc", donothing, free(DumpHexc(kHyperion, kHyperionSize, 0)));
|
||||||
|
}
|
|
@ -16,6 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/bits/bits.h"
|
||||||
#include "libc/stdio/append.internal.h"
|
#include "libc/stdio/append.internal.h"
|
||||||
#include "libc/testlib/ezbench.h"
|
#include "libc/testlib/ezbench.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
@ -87,8 +88,7 @@ TEST(appendw, test) {
|
||||||
EXPECT_EQ(0, b[0]);
|
EXPECT_EQ(0, b[0]);
|
||||||
EXPECT_EQ('h', b[1]);
|
EXPECT_EQ('h', b[1]);
|
||||||
EXPECT_EQ(0, b[2]);
|
EXPECT_EQ(0, b[2]);
|
||||||
ASSERT_NE(-1, appendw(&b, 'e' | 'l' << 8 | 'l' << 16 | 'o' << 24 |
|
ASSERT_NE(-1, appendw(&b, READ64LE("ello!\0\0")));
|
||||||
(uint64_t)'!' << 32));
|
|
||||||
EXPECT_EQ(7, appendz(b).i);
|
EXPECT_EQ(7, appendz(b).i);
|
||||||
EXPECT_EQ(0, b[0]);
|
EXPECT_EQ(0, b[0]);
|
||||||
EXPECT_EQ('h', b[1]);
|
EXPECT_EQ('h', b[1]);
|
||||||
|
@ -101,7 +101,7 @@ TEST(appendw, test) {
|
||||||
free(b);
|
free(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(appendr, test) {
|
TEST(appendr, testShrink_nulTerminates) {
|
||||||
char *b = 0;
|
char *b = 0;
|
||||||
ASSERT_NE(-1, appends(&b, "hello"));
|
ASSERT_NE(-1, appends(&b, "hello"));
|
||||||
EXPECT_EQ(5, appendz(b).i);
|
EXPECT_EQ(5, appendz(b).i);
|
||||||
|
@ -121,15 +121,54 @@ TEST(appendr, test) {
|
||||||
free(b);
|
free(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(appendr, testExtend_zeroFills) {
|
||||||
|
char *b = 0;
|
||||||
|
ASSERT_NE(-1, appends(&b, "hello"));
|
||||||
|
EXPECT_EQ(5, appendz(b).i);
|
||||||
|
ASSERT_NE(-1, appendr(&b, 20));
|
||||||
|
EXPECT_EQ(20, appendz(b).i);
|
||||||
|
ASSERT_BINEQ(u"hello ", b);
|
||||||
|
ASSERT_NE(-1, appendr(&b, 20));
|
||||||
|
EXPECT_EQ(20, appendz(b).i);
|
||||||
|
ASSERT_BINEQ(u"hello ", b);
|
||||||
|
free(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(appendr, testAbsent_allocatesNul) {
|
||||||
|
char *b = 0;
|
||||||
|
ASSERT_NE(-1, appendr(&b, 0));
|
||||||
|
EXPECT_EQ(0, appendz(b).i);
|
||||||
|
ASSERT_BINEQ(u" ", b);
|
||||||
|
free(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(appendd, testMemFail_doesntInitializePointer) {
|
||||||
|
char *b = 0;
|
||||||
|
ASSERT_EQ(-1, appendd(&b, 0, -1ull >> 8));
|
||||||
|
EXPECT_EQ(0, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(appendd, testMemFail_doesntFreeExistingAllocation) {
|
||||||
|
char *b = 0;
|
||||||
|
ASSERT_NE(-1, appends(&b, "hello"));
|
||||||
|
EXPECT_STREQ("hello", b);
|
||||||
|
ASSERT_EQ(-1, appendd(&b, 0, -1ull >> 8));
|
||||||
|
EXPECT_STREQ("hello", b);
|
||||||
|
free(b);
|
||||||
|
}
|
||||||
|
|
||||||
BENCH(vappendf, bench) {
|
BENCH(vappendf, bench) {
|
||||||
const char t[] = {0};
|
const char t[] = {0};
|
||||||
char *b = 0;
|
char *b = 0;
|
||||||
EZBENCH2("appendf", donothing, appendf(&b, "1"));
|
EZBENCH2("appendf", donothing, appendf(&b, "hello"));
|
||||||
free(b), b = 0;
|
free(b), b = 0;
|
||||||
EZBENCH2("appends", donothing, appends(&b, "1"));
|
EZBENCH2("appends", donothing, appends(&b, "hello"));
|
||||||
free(b), b = 0;
|
free(b), b = 0;
|
||||||
EZBENCH2("appendw", donothing, appendw(&b, 'B'));
|
EZBENCH2("appendw", donothing,
|
||||||
|
appendw(&b, 'h' | 'e' << 8 | 'l' << 16 | 'l' << 24 |
|
||||||
|
(uint64_t)'o' << 32));
|
||||||
free(b), b = 0;
|
free(b), b = 0;
|
||||||
EZBENCH2("appendd", donothing, appendd(&b, t, 1));
|
EZBENCH2("appendd", donothing, appendd(&b, "hello", 5));
|
||||||
|
EZBENCH2("appendr", donothing, appendr(&b, 0));
|
||||||
free(b), b = 0;
|
free(b), b = 0;
|
||||||
}
|
}
|
||||||
|
|
47
third_party/lua/lapi.c
vendored
47
third_party/lua/lapi.c
vendored
|
@ -18,7 +18,6 @@
|
||||||
#include "third_party/lua/lstate.h"
|
#include "third_party/lua/lstate.h"
|
||||||
#include "third_party/lua/lstring.h"
|
#include "third_party/lua/lstring.h"
|
||||||
#include "third_party/lua/ltable.h"
|
#include "third_party/lua/ltable.h"
|
||||||
#include "third_party/lua/larray.h"
|
|
||||||
#include "third_party/lua/ltm.h"
|
#include "third_party/lua/ltm.h"
|
||||||
#include "third_party/lua/lua.h"
|
#include "third_party/lua/lua.h"
|
||||||
#include "third_party/lua/lundump.h"
|
#include "third_party/lua/lundump.h"
|
||||||
|
@ -313,12 +312,6 @@ LUA_API int lua_isuserdata (lua_State *L, int idx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LUA_API int lua_isarray (lua_State *L, int idx) {
|
|
||||||
const TValue *o = index2value(L, idx);
|
|
||||||
return (isvalid(L, o) && ttype(o) == LUA_TTABLE && hvalue(o)->truearray);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
|
LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
|
||||||
const TValue *o1 = index2value(L, index1);
|
const TValue *o1 = index2value(L, index1);
|
||||||
const TValue *o2 = index2value(L, index2);
|
const TValue *o2 = index2value(L, index2);
|
||||||
|
@ -766,41 +759,6 @@ LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LUA_API void lua_createarray (lua_State *L, int narray) {
|
|
||||||
Array *a;
|
|
||||||
lua_lock(L);
|
|
||||||
a = luaA_new(L);
|
|
||||||
setavalue2s(L, L->top, a);
|
|
||||||
api_incr_top(L);
|
|
||||||
if (narray > 0)
|
|
||||||
luaA_resize(L, a, narray);
|
|
||||||
luaC_checkGC(L);
|
|
||||||
lua_unlock(L);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LUA_API void lua_resize (lua_State *L, int idx, unsigned int size) {
|
|
||||||
TValue *o;
|
|
||||||
Table *t;
|
|
||||||
unsigned int i, oldsize;
|
|
||||||
lua_lock(L);
|
|
||||||
o = index2value(L, idx);
|
|
||||||
api_check(L, ttistable(o), "table expected");
|
|
||||||
t = hvalue(o);
|
|
||||||
oldsize = t->sizeused;
|
|
||||||
if (size > luaH_realasize(t)) {
|
|
||||||
luaH_resizearray(L, t, size);
|
|
||||||
}
|
|
||||||
lua_unlock(L);
|
|
||||||
/* set removed elements to nil when shrinking array size */
|
|
||||||
for(i = size + 1; i <= oldsize; i++) {
|
|
||||||
lua_pushnil(L);
|
|
||||||
lua_seti(L, idx, i);
|
|
||||||
}
|
|
||||||
t->sizeused = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LUA_API int lua_getmetatable (lua_State *L, int objindex) {
|
LUA_API int lua_getmetatable (lua_State *L, int objindex) {
|
||||||
const TValue *obj;
|
const TValue *obj;
|
||||||
Table *mt;
|
Table *mt;
|
||||||
|
@ -909,10 +867,7 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, 1);
|
api_checknelems(L, 1);
|
||||||
t = index2value(L, idx);
|
t = index2value(L, idx);
|
||||||
if (ttisarray(t)) {
|
if (luaV_fastgeti(L, t, n, slot)) {
|
||||||
luaA_setint(L, avalue(t), n, s2v(L->top - 1));
|
|
||||||
}
|
|
||||||
else if (luaV_fastgeti(L, t, n, slot)) {
|
|
||||||
luaV_finishfastset(L, t, slot, s2v(L->top - 1));
|
luaV_finishfastset(L, t, slot, s2v(L->top - 1));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
107
third_party/lua/larray.c
vendored
107
third_party/lua/larray.c
vendored
|
@ -1,107 +0,0 @@
|
||||||
/*
|
|
||||||
** Lua arrays
|
|
||||||
** See Copyright Notice in lua.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
asm(".ident\t\"\\n\\n\
|
|
||||||
lua-array (MIT License)\\n\
|
|
||||||
Copyright 2018-2021 Petri Häkkinen\"");
|
|
||||||
asm(".include \"libc/disclaimer.inc\"");
|
|
||||||
|
|
||||||
#define larray_c
|
|
||||||
#define LUA_CORE
|
|
||||||
|
|
||||||
#include "third_party/lua/lprefix.h"
|
|
||||||
|
|
||||||
#include <libc/math.h>
|
|
||||||
#include <libc/limits.h>
|
|
||||||
|
|
||||||
#include "third_party/lua/lua.h"
|
|
||||||
|
|
||||||
#include "third_party/lua/ldebug.h"
|
|
||||||
#include "third_party/lua/ldo.h"
|
|
||||||
#include "third_party/lua/lgc.h"
|
|
||||||
#include "third_party/lua/lmem.h"
|
|
||||||
#include "third_party/lua/lobject.h"
|
|
||||||
#include "third_party/lua/lstate.h"
|
|
||||||
#include "third_party/lua/lstring.h"
|
|
||||||
#include "third_party/lua/ltable.h"
|
|
||||||
#include "third_party/lua/larray.h"
|
|
||||||
#include "third_party/lua/lvm.h"
|
|
||||||
|
|
||||||
Array *luaA_new (lua_State *L) {
|
|
||||||
GCObject *o = luaC_newobj(L, LUA_TARRAY, sizeof(Array));
|
|
||||||
Array *a = gco2a(o);
|
|
||||||
a->array = NULL;
|
|
||||||
a->alimit = 0;
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void luaA_resize (lua_State *L, Array *a, unsigned int newsize) {
|
|
||||||
unsigned int i;
|
|
||||||
unsigned int oldsize = a->alimit;
|
|
||||||
TValue *newarray;
|
|
||||||
|
|
||||||
/* allocate new array */
|
|
||||||
newarray = luaM_reallocvector(L, a->array, oldsize, newsize, TValue);
|
|
||||||
if (newarray == NULL && newsize > 0) { /* allocation failed? */
|
|
||||||
luaM_error(L); /* raise error (with array unchanged) */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allocation ok; initialize new part of the array */
|
|
||||||
a->array = newarray; /* set new array part */
|
|
||||||
a->alimit = newsize;
|
|
||||||
for (i = oldsize; i < newsize; i++) /* clear new slice of the array */
|
|
||||||
setempty(&a->array[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void luaA_free (lua_State *L, Array *a) {
|
|
||||||
luaM_freearray(L, a->array, a->alimit);
|
|
||||||
luaM_free(L, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const TValue *luaA_getint (lua_State *L, Array *a, lua_Integer key) {
|
|
||||||
/* (1 <= key && key <= t->alimit) */
|
|
||||||
if (l_castS2U(key) - 1u < a->alimit)
|
|
||||||
return &a->array[key - 1];
|
|
||||||
else
|
|
||||||
return luaO_nilobject;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TValue *luaA_get (lua_State *L, Array *a, const TValue *key) {
|
|
||||||
if (ttypetag(key) == LUA_VNUMINT) {
|
|
||||||
lua_Integer ikey = ivalue(key);
|
|
||||||
if (l_castS2U(ikey) - 1u < a->alimit)
|
|
||||||
return &a->array[ikey - 1];
|
|
||||||
else
|
|
||||||
return luaO_nilobject;
|
|
||||||
} else {
|
|
||||||
return luaO_nilobject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void luaA_setint (lua_State *L, Array *a, lua_Integer key, TValue *value) {
|
|
||||||
if (l_castS2U(key) - 1u < a->alimit) {
|
|
||||||
/* set value! */
|
|
||||||
TValue* val = &a->array[key - 1];
|
|
||||||
val->value_ = value->value_;
|
|
||||||
val->tt_ = value->tt_;
|
|
||||||
checkliveness(L,val);
|
|
||||||
} else {
|
|
||||||
/* TODO: this error message could be improved! */
|
|
||||||
luaG_runerror(L, "array index out of bounds");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void luaA_set (lua_State *L, Array *a, const TValue* key, TValue *value) {
|
|
||||||
if (ttypetag(key) == LUA_VNUMINT) {
|
|
||||||
lua_Integer ikey = ivalue(key);
|
|
||||||
luaA_setint(L, a, ikey, value);
|
|
||||||
} else {
|
|
||||||
/* TODO: the error message could be improved */
|
|
||||||
luaG_runerror(L, "attempt to index array with a non-integer value");
|
|
||||||
}
|
|
||||||
}
|
|
22
third_party/lua/larray.h
vendored
22
third_party/lua/larray.h
vendored
|
@ -1,22 +0,0 @@
|
||||||
/*
|
|
||||||
** Lua arrays
|
|
||||||
** See Copyright Notice in lua.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef larray_h
|
|
||||||
#define larray_h
|
|
||||||
|
|
||||||
#include "third_party/lua/lobject.h"
|
|
||||||
|
|
||||||
#define luaO_nilobject (&G(L)->nilvalue)
|
|
||||||
|
|
||||||
LUAI_FUNC Array *luaA_new (lua_State *L);
|
|
||||||
LUAI_FUNC void luaA_resize (lua_State *L, Array *a, unsigned int nsize);
|
|
||||||
LUAI_FUNC void luaA_free (lua_State *L, Array *a);
|
|
||||||
|
|
||||||
LUAI_FUNC const TValue *luaA_getint (lua_State *L, Array *a, lua_Integer key);
|
|
||||||
LUAI_FUNC void luaA_setint (lua_State *L, Array *a, lua_Integer key, TValue *value);
|
|
||||||
LUAI_FUNC const TValue *luaA_get (lua_State *L, Array *a, const TValue *key);
|
|
||||||
LUAI_FUNC void luaA_set (lua_State *L, Array *a, const TValue *key, TValue *value);
|
|
||||||
|
|
||||||
#endif
|
|
15
third_party/lua/lbaselib.c
vendored
15
third_party/lua/lbaselib.c
vendored
|
@ -254,12 +254,9 @@ static int luaB_next (lua_State *L) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int luaB_ipairs (lua_State *L);
|
|
||||||
|
|
||||||
static int luaB_pairs (lua_State *L) {
|
static int luaB_pairs (lua_State *L) {
|
||||||
luaL_checkany(L, 1);
|
luaL_checkany(L, 1);
|
||||||
if (lua_isarray(L, 1))
|
|
||||||
return luaB_ipairs(L);
|
|
||||||
if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */
|
if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */
|
||||||
lua_pushcfunction(L, luaB_next); /* will return generator, */
|
lua_pushcfunction(L, luaB_next); /* will return generator, */
|
||||||
lua_pushvalue(L, 1); /* state, */
|
lua_pushvalue(L, 1); /* state, */
|
||||||
|
@ -282,16 +279,6 @@ static int ipairsaux (lua_State *L) {
|
||||||
return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2;
|
return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** Traversal function for 'ipairs' specialized for arrays.
|
|
||||||
*/
|
|
||||||
static int ipairsauxarray (lua_State *L) {
|
|
||||||
lua_Integer i = luaL_checkinteger(L, 2) + 1;
|
|
||||||
lua_pushinteger(L, i);
|
|
||||||
lua_geti(L, 1, i);
|
|
||||||
return (lua_rawlen(L, 1) == i-1) ? 1 : 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
|
** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
|
||||||
|
@ -299,7 +286,7 @@ static int ipairsauxarray (lua_State *L) {
|
||||||
*/
|
*/
|
||||||
static int luaB_ipairs (lua_State *L) {
|
static int luaB_ipairs (lua_State *L) {
|
||||||
luaL_checkany(L, 1);
|
luaL_checkany(L, 1);
|
||||||
lua_pushcfunction(L, lua_isarray(L, 1) ? ipairsauxarray : ipairsaux); /* iteration function */
|
lua_pushcfunction(L, ipairsaux); /* iteration function */
|
||||||
lua_pushvalue(L, 1); /* state */
|
lua_pushvalue(L, 1); /* state */
|
||||||
lua_pushinteger(L, 0); /* initial value */
|
lua_pushinteger(L, 0); /* initial value */
|
||||||
return 3;
|
return 3;
|
||||||
|
|
2
third_party/lua/ldebug.c
vendored
2
third_party/lua/ldebug.c
vendored
|
@ -688,7 +688,7 @@ static const char *varinfo (lua_State *L, const TValue *o) {
|
||||||
|
|
||||||
l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
|
l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
|
||||||
const char *t = luaT_objtypename(L, o);
|
const char *t = luaT_objtypename(L, o);
|
||||||
luaG_runerror(L, "attempt to %s a%s %s value%s", op, ttisarray(o) ? "n" : "", t, varinfo(L, o));
|
luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
4
third_party/lua/lgc.c
vendored
4
third_party/lua/lgc.c
vendored
|
@ -17,7 +17,6 @@
|
||||||
#include "third_party/lua/lstate.h"
|
#include "third_party/lua/lstate.h"
|
||||||
#include "third_party/lua/lstring.h"
|
#include "third_party/lua/lstring.h"
|
||||||
#include "third_party/lua/ltable.h"
|
#include "third_party/lua/ltable.h"
|
||||||
#include "third_party/lua/larray.h"
|
|
||||||
#include "third_party/lua/ltm.h"
|
#include "third_party/lua/ltm.h"
|
||||||
#include "third_party/lua/lua.h"
|
#include "third_party/lua/lua.h"
|
||||||
|
|
||||||
|
@ -778,9 +777,6 @@ static void freeobj (lua_State *L, GCObject *o) {
|
||||||
case LUA_VTABLE:
|
case LUA_VTABLE:
|
||||||
luaH_free(L, gco2t(o));
|
luaH_free(L, gco2t(o));
|
||||||
break;
|
break;
|
||||||
case LUA_TARRAY:
|
|
||||||
luaA_free(L, gco2a(o));
|
|
||||||
break;
|
|
||||||
case LUA_VTHREAD:
|
case LUA_VTHREAD:
|
||||||
luaE_freethread(L, gco2th(o));
|
luaE_freethread(L, gco2th(o));
|
||||||
break;
|
break;
|
||||||
|
|
27
third_party/lua/lobject.h
vendored
27
third_party/lua/lobject.h
vendored
|
@ -722,8 +722,6 @@ typedef struct Table {
|
||||||
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
|
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
|
||||||
lu_byte lsizenode; /* log2 of size of 'node' array */
|
lu_byte lsizenode; /* log2 of size of 'node' array */
|
||||||
unsigned int alimit; /* "limit" of 'array' array */
|
unsigned int alimit; /* "limit" of 'array' array */
|
||||||
lu_byte truearray; /* 1 if the table is a true array (no hash part) */
|
|
||||||
unsigned int sizeused; /* size reported by objlen for true arrays (unused for regular tables) */
|
|
||||||
TValue *array; /* array part */
|
TValue *array; /* array part */
|
||||||
Node *node;
|
Node *node;
|
||||||
Node *lastfree; /* any free position is before this position */
|
Node *lastfree; /* any free position is before this position */
|
||||||
|
@ -793,31 +791,6 @@ LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
|
||||||
LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
|
LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
|
||||||
LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t srclen);
|
LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t srclen);
|
||||||
|
|
||||||
/*
|
|
||||||
** {==================================================================
|
|
||||||
** Arrays
|
|
||||||
** ===================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define ttisarray(o) checktag((o), ctb(LUA_TARRAY))
|
|
||||||
|
|
||||||
#define avalue(o) check_exp(ttisarray(o), gco2a(val_(o).gc))
|
|
||||||
|
|
||||||
#define setavalue(L,obj,x) \
|
|
||||||
{ TValue *io = (obj); Array *x_ = (x); \
|
|
||||||
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TARRAY)); \
|
|
||||||
checkliveness(L,io); }
|
|
||||||
|
|
||||||
#define setavalue2s(L,o,h) setavalue(L,s2v(o),h)
|
|
||||||
|
|
||||||
typedef struct Array {
|
|
||||||
CommonHeader;
|
|
||||||
unsigned int alimit; /* size of 'array' array */
|
|
||||||
TValue *array; /* array part */
|
|
||||||
GCObject *gclist;
|
|
||||||
} Array;
|
|
||||||
|
|
||||||
/* }================================================================== */
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
35
third_party/lua/lparser.c
vendored
35
third_party/lua/lparser.c
vendored
|
@ -905,14 +905,9 @@ static void field (LexState *ls, ConsControl *cc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void constructor (LexState *ls, expdesc *t, int array) {
|
static void constructor (LexState *ls, expdesc *t) {
|
||||||
/* constructor -> '{' [ field { sep field } [sep] ] '}'
|
/* constructor -> '{' [ field { sep field } [sep] ] '}'
|
||||||
sep -> ',' | ';' */
|
sep -> ',' | ';' */
|
||||||
|
|
||||||
/* special case for arrays (when 'array' is true):
|
|
||||||
constructor -> '[' [ listfield { sep listfield } [sep] ] ']'
|
|
||||||
sep -> ',' | ';' */
|
|
||||||
|
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
int line = ls->linenumber;
|
int line = ls->linenumber;
|
||||||
int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
|
int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
|
||||||
|
@ -923,32 +918,18 @@ static void constructor (LexState *ls, expdesc *t, int array) {
|
||||||
init_exp(t, VNONRELOC, fs->freereg); /* table will be at stack top */
|
init_exp(t, VNONRELOC, fs->freereg); /* table will be at stack top */
|
||||||
luaK_reserveregs(fs, 1);
|
luaK_reserveregs(fs, 1);
|
||||||
init_exp(&cc.v, VVOID, 0); /* no value (yet) */
|
init_exp(&cc.v, VVOID, 0); /* no value (yet) */
|
||||||
luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */
|
checknext(ls, '{');
|
||||||
checknext(ls, (array ? '[' : '{'));
|
|
||||||
do {
|
do {
|
||||||
lua_assert(cc.v.k == VVOID || cc.tostore > 0);
|
lua_assert(cc.v.k == VVOID || cc.tostore > 0);
|
||||||
if (ls->t.token == (array ? ']' : '}')) break;
|
if (ls->t.token == '}') break;
|
||||||
closelistfield(fs, &cc);
|
closelistfield(fs, &cc);
|
||||||
if (array)
|
|
||||||
listfield(ls, &cc);
|
|
||||||
else
|
|
||||||
field(ls, &cc);
|
field(ls, &cc);
|
||||||
} while (testnext(ls, ',') || testnext(ls, ';'));
|
} while (testnext(ls, ',') || testnext(ls, ';'));
|
||||||
check_match(ls, array ? ']' : '}', array ? '[' : '{', line);
|
check_match(ls, '}', '{', line);
|
||||||
lastlistfield(fs, &cc);
|
lastlistfield(fs, &cc);
|
||||||
luaK_settablesize(fs, pc, t->u.info, cc.na, cc.nh);
|
luaK_settablesize(fs, pc, t->u.info, cc.na, cc.nh);
|
||||||
/* encode arrayness by setting B to max value (255) */
|
|
||||||
if (array) {
|
|
||||||
/* make sure B is not already 255 */
|
|
||||||
/* I don't this can happen in practice (max size is luaO_fb2int(255) = 3221225472), but let's be sure... */
|
|
||||||
unsigned int b = GETARG_B(fs->f->code[pc]);
|
|
||||||
if (b == 255)
|
|
||||||
luaX_syntaxerror(fs->ls, "table too large");
|
|
||||||
SETARG_B(fs->f->code[pc], 255);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* }====================================================================== */
|
/* }====================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
@ -1042,7 +1023,7 @@ static void funcargs (LexState *ls, expdesc *f, int line) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case '{': { /* funcargs -> constructor */
|
case '{': { /* funcargs -> constructor */
|
||||||
constructor(ls, &args, 0);
|
constructor(ls, &args);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_STRING: { /* funcargs -> STRING */
|
case TK_STRING: { /* funcargs -> STRING */
|
||||||
|
@ -1177,11 +1158,7 @@ static void simpleexp (LexState *ls, expdesc *v) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case '{': { /* constructor */
|
case '{': { /* constructor */
|
||||||
constructor(ls, v, 0);
|
constructor(ls, v);
|
||||||
return;
|
|
||||||
}
|
|
||||||
case '[': { /* array constructor */
|
|
||||||
constructor(ls, v, 1);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case TK_FUNCTION: {
|
case TK_FUNCTION: {
|
||||||
|
|
2
third_party/lua/lstate.h
vendored
2
third_party/lua/lstate.h
vendored
|
@ -351,7 +351,6 @@ union GCUnion {
|
||||||
struct Udata u;
|
struct Udata u;
|
||||||
union Closure cl;
|
union Closure cl;
|
||||||
struct Table h;
|
struct Table h;
|
||||||
struct Array a;
|
|
||||||
struct Proto p;
|
struct Proto p;
|
||||||
struct lua_State th; /* thread */
|
struct lua_State th; /* thread */
|
||||||
struct UpVal upv;
|
struct UpVal upv;
|
||||||
|
@ -374,7 +373,6 @@ union GCUnion {
|
||||||
#define gco2cl(o) \
|
#define gco2cl(o) \
|
||||||
check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl))
|
check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl))
|
||||||
#define gco2t(o) check_exp((o)->tt == LUA_VTABLE, &((cast_u(o))->h))
|
#define gco2t(o) check_exp((o)->tt == LUA_VTABLE, &((cast_u(o))->h))
|
||||||
#define gco2a(o) check_exp((o)->tt == LUA_TARRAY, &((cast_u(o))->a))
|
|
||||||
#define gco2p(o) check_exp((o)->tt == LUA_VPROTO, &((cast_u(o))->p))
|
#define gco2p(o) check_exp((o)->tt == LUA_VPROTO, &((cast_u(o))->p))
|
||||||
#define gco2th(o) check_exp((o)->tt == LUA_VTHREAD, &((cast_u(o))->th))
|
#define gco2th(o) check_exp((o)->tt == LUA_VTHREAD, &((cast_u(o))->th))
|
||||||
#define gco2upv(o) check_exp((o)->tt == LUA_VUPVAL, &((cast_u(o))->upv))
|
#define gco2upv(o) check_exp((o)->tt == LUA_VUPVAL, &((cast_u(o))->upv))
|
||||||
|
|
24
third_party/lua/ltable.c
vendored
24
third_party/lua/ltable.c
vendored
|
@ -613,10 +613,8 @@ Table *luaH_new (lua_State *L) {
|
||||||
Table *t = gco2t(o);
|
Table *t = gco2t(o);
|
||||||
t->metatable = NULL;
|
t->metatable = NULL;
|
||||||
t->flags = cast_byte(maskflags); /* table has no metamethod fields */
|
t->flags = cast_byte(maskflags); /* table has no metamethod fields */
|
||||||
t->truearray = 0;
|
|
||||||
t->array = NULL;
|
t->array = NULL;
|
||||||
t->alimit = 0;
|
t->alimit = 0;
|
||||||
t->sizeused = 0;
|
|
||||||
setnodevector(L, t, 0);
|
setnodevector(L, t, 0);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
@ -654,25 +652,7 @@ void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) {
|
||||||
TValue aux;
|
TValue aux;
|
||||||
if (l_unlikely(ttisnil(key)))
|
if (l_unlikely(ttisnil(key)))
|
||||||
luaG_runerror(L, "table index is nil");
|
luaG_runerror(L, "table index is nil");
|
||||||
else if (t->truearray) {
|
else if (ttisfloat(key)) {
|
||||||
/* set new value to true array */
|
|
||||||
int capacity;
|
|
||||||
int asize = luaH_realasize(t);
|
|
||||||
int idx = ivalue(key); /* TODO: does not handle numbers larger than fits into a 32-bit signed integer! */
|
|
||||||
if (!ttisinteger(key) || idx < 1)
|
|
||||||
luaG_runerror(L, "invalid array index");
|
|
||||||
/* enlarge capacity */
|
|
||||||
if (asize < idx) {
|
|
||||||
capacity = asize + (asize >> 1);
|
|
||||||
if (capacity < idx)
|
|
||||||
capacity = idx;
|
|
||||||
luaH_resizearray(L, t, capacity);
|
|
||||||
}
|
|
||||||
t->sizeused = idx; // since this is guaranteed to be a new key, it exceeds t->sizeused
|
|
||||||
luaC_barrierback(L, obj2gco(t), key);
|
|
||||||
setobj2t(L, cast(TValue *, t->array + idx - 1), value);
|
|
||||||
return;
|
|
||||||
} else if (ttisfloat(key)) {
|
|
||||||
lua_Number f = fltvalue(key);
|
lua_Number f = fltvalue(key);
|
||||||
lua_Integer k;
|
lua_Integer k;
|
||||||
if (luaV_flttointeger(f, &k, F2Ieq)) { /* does key fit in an integer? */
|
if (luaV_flttointeger(f, &k, F2Ieq)) { /* does key fit in an integer? */
|
||||||
|
@ -927,8 +907,6 @@ static unsigned int binsearch (const TValue *array, unsigned int i,
|
||||||
*/
|
*/
|
||||||
lua_Unsigned luaH_getn (Table *t) {
|
lua_Unsigned luaH_getn (Table *t) {
|
||||||
unsigned int limit = t->alimit;
|
unsigned int limit = t->alimit;
|
||||||
if (t->truearray)
|
|
||||||
return t->sizeused;
|
|
||||||
if (limit > 0 && isempty(&t->array[limit - 1])) { /* (1)? */
|
if (limit > 0 && isempty(&t->array[limit - 1])) { /* (1)? */
|
||||||
/* there must be a boundary before 'limit' */
|
/* there must be a boundary before 'limit' */
|
||||||
if (limit >= 2 && !isempty(&t->array[limit - 2])) {
|
if (limit >= 2 && !isempty(&t->array[limit - 2])) {
|
||||||
|
|
13
third_party/lua/ltablib.c
vendored
13
third_party/lua/ltablib.c
vendored
|
@ -401,18 +401,6 @@ static int sort (lua_State *L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int resize (lua_State *L) {
|
|
||||||
/* reserve capacity of the array part -- useful when filling large tables/arrays */
|
|
||||||
int size;
|
|
||||||
luaL_checktype(L, 1, LUA_TTABLE);
|
|
||||||
size = luaL_checkinteger(L, 2);
|
|
||||||
luaL_argcheck(L, size >= 0, 2, "invalid size");
|
|
||||||
lua_resize(L, 1, (unsigned int)size);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* }====================================================== */
|
/* }====================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
@ -424,7 +412,6 @@ static const luaL_Reg tab_funcs[] = {
|
||||||
{"remove", tremove},
|
{"remove", tremove},
|
||||||
{"move", tmove},
|
{"move", tmove},
|
||||||
{"sort", sort},
|
{"sort", sort},
|
||||||
{"resize", resize},
|
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
3
third_party/lua/ltm.c
vendored
3
third_party/lua/ltm.c
vendored
|
@ -26,7 +26,7 @@ static const char udatatypename[] = "userdata";
|
||||||
LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTYPES] = {
|
LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTYPES] = {
|
||||||
"no value",
|
"no value",
|
||||||
"nil", "boolean", udatatypename, "number",
|
"nil", "boolean", udatatypename, "number",
|
||||||
"string", "table", "function", udatatypename, "thread", "array",
|
"string", "table", "function", udatatypename, "thread",
|
||||||
"upvalue", "proto" /* these last cases are used for tests only */
|
"upvalue", "proto" /* these last cases are used for tests only */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -264,3 +264,4 @@ void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) {
|
||||||
for (; i < wanted; i++) /* complete required results with nil */
|
for (; i < wanted; i++) /* complete required results with nil */
|
||||||
setnilvalue(s2v(where + i));
|
setnilvalue(s2v(where + i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
third_party/lua/lua.h
vendored
7
third_party/lua/lua.h
vendored
|
@ -60,8 +60,8 @@ typedef struct lua_State lua_State;
|
||||||
#define LUA_TFUNCTION 6
|
#define LUA_TFUNCTION 6
|
||||||
#define LUA_TUSERDATA 7
|
#define LUA_TUSERDATA 7
|
||||||
#define LUA_TTHREAD 8
|
#define LUA_TTHREAD 8
|
||||||
#define LUA_TARRAY 9
|
|
||||||
#define LUA_NUMTYPES 10
|
#define LUA_NUMTYPES 9
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -173,7 +173,6 @@ LUA_API int (lua_isstring) (lua_State *L, int idx);
|
||||||
LUA_API int (lua_iscfunction) (lua_State *L, int idx);
|
LUA_API int (lua_iscfunction) (lua_State *L, int idx);
|
||||||
LUA_API int (lua_isinteger) (lua_State *L, int idx);
|
LUA_API int (lua_isinteger) (lua_State *L, int idx);
|
||||||
LUA_API int (lua_isuserdata) (lua_State *L, int idx);
|
LUA_API int (lua_isuserdata) (lua_State *L, int idx);
|
||||||
LUA_API int (lua_isarray) (lua_State *L, int idx);
|
|
||||||
LUA_API int (lua_type) (lua_State *L, int idx);
|
LUA_API int (lua_type) (lua_State *L, int idx);
|
||||||
LUA_API const char *(lua_typename) (lua_State *L, int tp);
|
LUA_API const char *(lua_typename) (lua_State *L, int tp);
|
||||||
|
|
||||||
|
@ -246,8 +245,6 @@ LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
|
||||||
LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p);
|
LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p);
|
||||||
|
|
||||||
LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
|
LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
|
||||||
LUA_API void (lua_createarray) (lua_State *L, int narr);
|
|
||||||
LUA_API void (lua_resize) (lua_State *L, int idx, unsigned int size);
|
|
||||||
LUA_API void *(lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue);
|
LUA_API void *(lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue);
|
||||||
LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
|
LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
|
||||||
LUA_API int (lua_getiuservalue) (lua_State *L, int idx, int n);
|
LUA_API int (lua_getiuservalue) (lua_State *L, int idx, int n);
|
||||||
|
|
37
third_party/lua/lvm.c
vendored
37
third_party/lua/lvm.c
vendored
|
@ -17,7 +17,6 @@
|
||||||
#include "third_party/lua/lstate.h"
|
#include "third_party/lua/lstate.h"
|
||||||
#include "third_party/lua/lstring.h"
|
#include "third_party/lua/lstring.h"
|
||||||
#include "third_party/lua/ltable.h"
|
#include "third_party/lua/ltable.h"
|
||||||
#include "third_party/lua/larray.h"
|
|
||||||
#include "third_party/lua/ltm.h"
|
#include "third_party/lua/ltm.h"
|
||||||
#include "third_party/lua/lua.h"
|
#include "third_party/lua/lua.h"
|
||||||
#include "third_party/lua/lvm.h"
|
#include "third_party/lua/lvm.h"
|
||||||
|
@ -284,11 +283,6 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
|
||||||
for (loop = 0; loop < MAXTAGLOOP; loop++) {
|
for (loop = 0; loop < MAXTAGLOOP; loop++) {
|
||||||
if (slot == NULL) { /* 't' is not a table? */
|
if (slot == NULL) { /* 't' is not a table? */
|
||||||
lua_assert(!ttistable(t));
|
lua_assert(!ttistable(t));
|
||||||
if (ttisarray(t)) {
|
|
||||||
/* get array value */
|
|
||||||
setobj2s(L, val, luaA_get(L, avalue(t), key));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tm = luaT_gettmbyobj(L, t, TM_INDEX);
|
tm = luaT_gettmbyobj(L, t, TM_INDEX);
|
||||||
if (l_unlikely(notm(tm)))
|
if (l_unlikely(notm(tm)))
|
||||||
luaG_typeerror(L, t, "index"); /* no metamethod */
|
luaG_typeerror(L, t, "index"); /* no metamethod */
|
||||||
|
@ -337,17 +331,12 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
||||||
if (tm == NULL) { /* no metamethod? */
|
if (tm == NULL) { /* no metamethod? */
|
||||||
luaH_finishset(L, h, key, slot, val); /* set new value */
|
luaH_finishset(L, h, key, slot, val); /* set new value */
|
||||||
invalidateTMcache(h);
|
invalidateTMcache(h);
|
||||||
/* enlarge array length when necessary */
|
|
||||||
/* this should be quite fast as fields of h and key have already been loaded to CPU cache at this point */
|
|
||||||
h->sizeused += (val_(key).i > h->sizeused) & ttisinteger(key) & 1;
|
|
||||||
luaC_barrierback(L, obj2gco(h), val);
|
luaC_barrierback(L, obj2gco(h), val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* else will try the metamethod */
|
/* else will try the metamethod */
|
||||||
}
|
}
|
||||||
else { /* not a table; check metamethod */
|
else { /* not a table; check metamethod */
|
||||||
if(ttisarray(t))
|
|
||||||
luaG_typeerror(L, t, "set non-integer index of");
|
|
||||||
tm = luaT_gettmbyobj(L, t, TM_NEWINDEX);
|
tm = luaT_gettmbyobj(L, t, TM_NEWINDEX);
|
||||||
if (l_unlikely(notm(tm)))
|
if (l_unlikely(notm(tm)))
|
||||||
luaG_typeerror(L, t, "index");
|
luaG_typeerror(L, t, "index");
|
||||||
|
@ -693,11 +682,6 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
|
||||||
setivalue(s2v(ra), luaH_getn(h)); /* else primitive len */
|
setivalue(s2v(ra), luaH_getn(h)); /* else primitive len */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case LUA_TARRAY: {
|
|
||||||
Array *a = avalue(rb);
|
|
||||||
setivalue(s2v(ra), a->alimit);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case LUA_VSHRSTR: {
|
case LUA_VSHRSTR: {
|
||||||
setivalue(s2v(ra), tsvalue(rb)->shrlen);
|
setivalue(s2v(ra), tsvalue(rb)->shrlen);
|
||||||
return;
|
return;
|
||||||
|
@ -1257,10 +1241,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
const TValue *slot;
|
const TValue *slot;
|
||||||
TValue *rb = vRB(i);
|
TValue *rb = vRB(i);
|
||||||
int c = GETARG_C(i);
|
int c = GETARG_C(i);
|
||||||
if(ttisarray(rb)) {
|
if (luaV_fastgeti(L, rb, c, slot)) {
|
||||||
setobj2s(L, ra, luaA_getint(L, avalue(rb), c));
|
|
||||||
}
|
|
||||||
else if (luaV_fastgeti(L, rb, c, slot)) {
|
|
||||||
setobj2s(L, ra, slot);
|
setobj2s(L, ra, slot);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1313,10 +1294,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
const TValue *slot;
|
const TValue *slot;
|
||||||
int c = GETARG_B(i);
|
int c = GETARG_B(i);
|
||||||
TValue *rc = RKC(i);
|
TValue *rc = RKC(i);
|
||||||
if(ttisarray(s2v(ra))) {
|
if (luaV_fastgeti(L, s2v(ra), c, slot)) {
|
||||||
luaA_setint(L, avalue(s2v(ra)), c, rc);
|
|
||||||
}
|
|
||||||
else if (luaV_fastgeti(L, s2v(ra), c, slot)) {
|
|
||||||
luaV_finishfastset(L, s2v(ra), slot, rc);
|
luaV_finishfastset(L, s2v(ra), slot, rc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1341,8 +1319,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
vmcase(OP_NEWTABLE) {
|
vmcase(OP_NEWTABLE) {
|
||||||
int b = GETARG_B(i); /* log2(hash size) + 1 */
|
int b = GETARG_B(i); /* log2(hash size) + 1 */
|
||||||
int c = GETARG_C(i); /* array size */
|
int c = GETARG_C(i); /* array size */
|
||||||
/* decode arrayness */
|
|
||||||
int array = (b == 255);
|
|
||||||
Table *t;
|
Table *t;
|
||||||
if (b > 0)
|
if (b > 0)
|
||||||
b = 1 << (b - 1); /* size is 2^(b - 1) */
|
b = 1 << (b - 1); /* size is 2^(b - 1) */
|
||||||
|
@ -1352,16 +1328,9 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
pc++; /* skip extra argument */
|
pc++; /* skip extra argument */
|
||||||
L->top = ra + 1; /* correct top in case of emergency GC */
|
L->top = ra + 1; /* correct top in case of emergency GC */
|
||||||
t = luaH_new(L); /* memory allocation */
|
t = luaH_new(L); /* memory allocation */
|
||||||
t->truearray = array;
|
|
||||||
t->sizeused = c;
|
|
||||||
sethvalue2s(L, ra, t);
|
sethvalue2s(L, ra, t);
|
||||||
if (b != 0 || c != 0) {
|
if (b != 0 || c != 0)
|
||||||
if (array) {
|
|
||||||
luaH_resizearray(L, t, c); /* idem */
|
|
||||||
} else {
|
|
||||||
luaH_resize(L, t, c, b); /* idem */
|
luaH_resize(L, t, c, b); /* idem */
|
||||||
}
|
|
||||||
}
|
|
||||||
checkGC(L, ra + 1);
|
checkGC(L, ra + 1);
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
|
|
15
third_party/lua/lvm.h
vendored
15
third_party/lua/lvm.h
vendored
|
@ -88,13 +88,6 @@ typedef enum {
|
||||||
: (slot = f(hvalue(t), k), /* else, do raw access */ \
|
: (slot = f(hvalue(t), k), /* else, do raw access */ \
|
||||||
!isempty(slot))) /* result not empty? */
|
!isempty(slot))) /* result not empty? */
|
||||||
|
|
||||||
/* This one supports arrays as well as tables. */
|
|
||||||
#define luaV_fastget2(L,t,k,slot,f) \
|
|
||||||
(ttisarray(t) ? (slot = f(avalue(t), k), !isempty(slot)) : \
|
|
||||||
(!ttistable(t) \
|
|
||||||
? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
|
|
||||||
: (slot = f(hvalue(t), k), /* else, do raw access */ \
|
|
||||||
!isempty(slot)))) /* result not empty? */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Special case of 'luaV_fastget' for integers, inlining the fast case
|
** Special case of 'luaV_fastget' for integers, inlining the fast case
|
||||||
|
@ -107,14 +100,6 @@ typedef enum {
|
||||||
? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \
|
? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \
|
||||||
!isempty(slot))) /* result not empty? */
|
!isempty(slot))) /* result not empty? */
|
||||||
|
|
||||||
/* This one supports arrays as well as tables. */
|
|
||||||
#define luaV_fastgeti2(L,t,k,slot) \
|
|
||||||
(ttisarray(t) ? (slot = (l_castS2U(k) - 1u < avalue(t)->sizearray) ? &avalue(t)->array[k - 1] : luaO_nilobject, !isempty(slot)) : \
|
|
||||||
(!ttistable(t) \
|
|
||||||
? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
|
|
||||||
: (slot = (l_castS2U(k) - 1u < hvalue(t)->sizearray) \
|
|
||||||
? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \
|
|
||||||
!isempty(slot)))) /* result not empty? */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Finish a fast set operation (when fast get succeeds). In that case,
|
** Finish a fast set operation (when fast get succeeds). In that case,
|
||||||
|
|
211
third_party/lua/test/arrays.lua
vendored
211
third_party/lua/test/arrays.lua
vendored
|
@ -1,211 +0,0 @@
|
||||||
local errors = false
|
|
||||||
|
|
||||||
function assert(cond)
|
|
||||||
if not cond then
|
|
||||||
local line = debug.getinfo(2).currentline
|
|
||||||
print("test failed at line " .. line)
|
|
||||||
errors = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test array constructor
|
|
||||||
do
|
|
||||||
local a = [1, 2, 3]
|
|
||||||
assert(a[1] == 1)
|
|
||||||
assert(a[2] == 2)
|
|
||||||
assert(a[3] == 3)
|
|
||||||
assert(#a == 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test nested array constructor
|
|
||||||
do
|
|
||||||
local a = [1, 2, 3, [4, 5]]
|
|
||||||
assert(a[1] == 1)
|
|
||||||
assert(a[2] == 2)
|
|
||||||
assert(a[3] == 3)
|
|
||||||
assert(a[4][1] == 4)
|
|
||||||
assert(a[4][2] == 5)
|
|
||||||
assert(#a == 4)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test array write
|
|
||||||
do
|
|
||||||
local a = [1, 2, 3]
|
|
||||||
a[1] = -1
|
|
||||||
assert(a[1] == -1)
|
|
||||||
assert(#a == 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test array extend
|
|
||||||
do
|
|
||||||
local a = [1, 2, 3]
|
|
||||||
a[7] = 5
|
|
||||||
assert(#a == 7)
|
|
||||||
assert(a[7] == 5)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test array extend 2
|
|
||||||
do
|
|
||||||
local a = []
|
|
||||||
for i=5,15 do
|
|
||||||
a[i] = i
|
|
||||||
assert(a[i] == i)
|
|
||||||
assert(#a == i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test setting element to nil (should not affect array size)
|
|
||||||
do
|
|
||||||
local a = [1, 2, 3]
|
|
||||||
a[3] = nil
|
|
||||||
assert(a[3] == nil)
|
|
||||||
assert(#a == 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test array with holes
|
|
||||||
do
|
|
||||||
local a = [1, nil, 3]
|
|
||||||
assert(a[1] == 1)
|
|
||||||
assert(a[2] == nil)
|
|
||||||
assert(a[3] == 3)
|
|
||||||
assert(#a == 3)
|
|
||||||
a[1] = nil
|
|
||||||
assert(#a == 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test filling hole in array
|
|
||||||
do
|
|
||||||
local a = [1, nil, 3]
|
|
||||||
a[2] = 2
|
|
||||||
assert(a[2] == 2)
|
|
||||||
assert(#a == 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test filling hole in array 2
|
|
||||||
do
|
|
||||||
local a = [1, nil, 3]
|
|
||||||
local i = 2
|
|
||||||
a[i] = 2
|
|
||||||
assert(a[2] == 2)
|
|
||||||
assert(#a == 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test read out of bounds
|
|
||||||
do
|
|
||||||
local a = [1, 2, 3]
|
|
||||||
assert(#a == 3)
|
|
||||||
assert(a[0] == nil)
|
|
||||||
assert(a[4] == nil)
|
|
||||||
assert(#a == 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test array resize (array growing)
|
|
||||||
do
|
|
||||||
local a = [1, 2, 3]
|
|
||||||
table.resize(a, 1000)
|
|
||||||
assert(a[4] == nil)
|
|
||||||
assert(#a == 1000)
|
|
||||||
a[1] = 4
|
|
||||||
a[10] = 10
|
|
||||||
a[11] = 11
|
|
||||||
assert(#a == 1000)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test array resize (array shrinking)
|
|
||||||
do
|
|
||||||
local a = [1, 2, 3, 4, 5]
|
|
||||||
table.resize(a, 3)
|
|
||||||
assert(a[1] == 1)
|
|
||||||
assert(a[2] == 2)
|
|
||||||
assert(a[3] == 3)
|
|
||||||
assert(a[4] == nil)
|
|
||||||
assert(a[5] == nil)
|
|
||||||
assert(#a == 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test non-const integer
|
|
||||||
do
|
|
||||||
local a = []
|
|
||||||
local y = 3
|
|
||||||
a[y] = 66
|
|
||||||
assert(a[3] == 66)
|
|
||||||
assert(#a == 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test table.insert()
|
|
||||||
do
|
|
||||||
local a = [1, 2, 3]
|
|
||||||
table.insert(a, 1, "new")
|
|
||||||
assert(a[1] == "new")
|
|
||||||
assert(a[2] == 1)
|
|
||||||
assert(a[3] == 2)
|
|
||||||
assert(a[4] == 3)
|
|
||||||
assert(#a == 4)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test table.remove()
|
|
||||||
do
|
|
||||||
local a = [1, 2, 3]
|
|
||||||
table.remove(a, 1)
|
|
||||||
assert(a[1] == 2)
|
|
||||||
assert(a[2] == 3)
|
|
||||||
-- TODO: fix the implementation, as after upgrading to Lua 5.4.3
|
|
||||||
-- it keeps the array size the same after table.remove()
|
|
||||||
-- assert(#a == 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test ipairs
|
|
||||||
-- expected behavior: equivalent to for i=1,#a do print(i, a[i]) end
|
|
||||||
do
|
|
||||||
local a = [1, nil, 3, nil]
|
|
||||||
local cnt = 0
|
|
||||||
for k,v in ipairs(a) do
|
|
||||||
assert(v == a[k])
|
|
||||||
cnt = cnt + 1
|
|
||||||
end
|
|
||||||
assert(cnt == #a)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test pairs
|
|
||||||
-- expected behavior: same as ipairs?
|
|
||||||
do
|
|
||||||
local a = [1, nil, 3]
|
|
||||||
local cnt = 0
|
|
||||||
for k,v in pairs(a) do
|
|
||||||
assert(v == a[k])
|
|
||||||
cnt = cnt + 1
|
|
||||||
end
|
|
||||||
assert(cnt == 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- test normal insert/remove operations
|
|
||||||
local function test (a)
|
|
||||||
assert(not pcall(table.insert, a, 2, 20));
|
|
||||||
table.insert(a, 10);
|
|
||||||
table.insert(a, 2, 20);
|
|
||||||
table.insert(a, 1, -1);
|
|
||||||
table.insert(a, 40);
|
|
||||||
table.insert(a, #a+1, 50)
|
|
||||||
table.insert(a, 2, -2)
|
|
||||||
assert(a[2] ~= undef)
|
|
||||||
assert(a["2"] == undef)
|
|
||||||
assert(not pcall(table.insert, a, 0, 20));
|
|
||||||
assert(not pcall(table.insert, a, #a + 2, 20));
|
|
||||||
assert(table.remove(a,1) == -1)
|
|
||||||
assert(table.remove(a,1) == -2)
|
|
||||||
assert(table.remove(a,1) == 10)
|
|
||||||
assert(table.remove(a,1) == 20)
|
|
||||||
assert(table.remove(a,1) == 40)
|
|
||||||
assert(table.remove(a,1) == 50)
|
|
||||||
assert(table.remove(a,1) == nil)
|
|
||||||
assert(table.remove(a) == nil)
|
|
||||||
assert(table.remove(a, #a) == nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
a = {n=0, [-7] = "ban"}
|
|
||||||
test(a)
|
|
||||||
assert(a.n == 0 and a[-7] == "ban")
|
|
||||||
|
|
||||||
if not errors then
|
|
||||||
print("All tests passed!")
|
|
||||||
end
|
|
4
third_party/mbedtls/config.h
vendored
4
third_party/mbedtls/config.h
vendored
|
@ -64,6 +64,7 @@
|
||||||
/* key exchange */
|
/* key exchange */
|
||||||
#define MBEDTLS_RSA_C
|
#define MBEDTLS_RSA_C
|
||||||
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
|
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
|
||||||
|
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||||
#ifndef TINY
|
#ifndef TINY
|
||||||
#define MBEDTLS_ECP_C
|
#define MBEDTLS_ECP_C
|
||||||
#define MBEDTLS_ECDH_C
|
#define MBEDTLS_ECDH_C
|
||||||
|
@ -72,13 +73,12 @@
|
||||||
#define MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED
|
#define MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED
|
||||||
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||||
#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
|
#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
|
||||||
|
#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
|
||||||
/*#define MBEDTLS_DHM_C*/
|
/*#define MBEDTLS_DHM_C*/
|
||||||
/*#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED*/
|
/*#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED*/
|
||||||
/*#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED*/
|
/*#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED*/
|
||||||
/*#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED*/
|
/*#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED*/
|
||||||
/*#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED*/
|
|
||||||
/*#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED*/
|
/*#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED*/
|
||||||
/*#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED*/
|
|
||||||
/*#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED*/
|
/*#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
3
third_party/mbedtls/dhm.c
vendored
3
third_party/mbedtls/dhm.c
vendored
|
@ -17,6 +17,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "third_party/mbedtls/asn1.h"
|
#include "third_party/mbedtls/asn1.h"
|
||||||
|
#include "third_party/mbedtls/bignum.h"
|
||||||
#include "third_party/mbedtls/common.h"
|
#include "third_party/mbedtls/common.h"
|
||||||
#include "third_party/mbedtls/dhm.h"
|
#include "third_party/mbedtls/dhm.h"
|
||||||
#include "third_party/mbedtls/error.h"
|
#include "third_party/mbedtls/error.h"
|
||||||
|
@ -322,7 +323,7 @@ static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
|
||||||
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
|
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
|
||||||
|
|
||||||
while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
|
while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
|
||||||
mbedtls_mpi_shift_r( &R, 1 );
|
mbedtls_mpi_shift_r( R, 1 );
|
||||||
|
|
||||||
if( count++ > 10 )
|
if( count++ > 10 )
|
||||||
return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
|
return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
|
||||||
|
|
2
third_party/mbedtls/ssl.h
vendored
2
third_party/mbedtls/ssl.h
vendored
|
@ -1419,7 +1419,7 @@ int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *, mbedtls_dhm_context * )
|
||||||
int mbedtls_ssl_conf_dtls_srtp_protection_profiles( mbedtls_ssl_config *, const mbedtls_ssl_srtp_profile * );
|
int mbedtls_ssl_conf_dtls_srtp_protection_profiles( mbedtls_ssl_config *, const mbedtls_ssl_srtp_profile * );
|
||||||
int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *, unsigned char );
|
int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *, unsigned char );
|
||||||
int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *, mbedtls_x509_crt *, mbedtls_pk_context * );
|
int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *, mbedtls_x509_crt *, mbedtls_pk_context * );
|
||||||
int mbedtls_ssl_conf_psk( mbedtls_ssl_config *, const unsigned char *, size_t, const unsigned char *, size_t );
|
int mbedtls_ssl_conf_psk( mbedtls_ssl_config *, const void *, size_t, const void *, size_t );
|
||||||
int mbedtls_ssl_context_load( mbedtls_ssl_context *, const unsigned char *, size_t );
|
int mbedtls_ssl_context_load( mbedtls_ssl_context *, const unsigned char *, size_t );
|
||||||
int mbedtls_ssl_context_save( mbedtls_ssl_context *, unsigned char *, size_t, size_t * );
|
int mbedtls_ssl_context_save( mbedtls_ssl_context *, unsigned char *, size_t, size_t * );
|
||||||
int mbedtls_ssl_get_ciphersuite_id( const char * );
|
int mbedtls_ssl_get_ciphersuite_id( const char * );
|
||||||
|
|
53
third_party/mbedtls/ssl_ciphersuites.c
vendored
53
third_party/mbedtls/ssl_ciphersuites.c
vendored
|
@ -72,16 +72,19 @@ static const uint16_t ciphersuite_preference[] =
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED
|
#ifdef MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED
|
||||||
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
|
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384,
|
||||||
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
|
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256,
|
||||||
|
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256,
|
||||||
MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
||||||
MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
||||||
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
|
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
|
||||||
|
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
|
||||||
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
|
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
|
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
|
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||||
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
|
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
|
||||||
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
|
|
||||||
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
|
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
|
||||||
|
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
|
||||||
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
|
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
|
||||||
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
|
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
|
||||||
#endif
|
#endif
|
||||||
|
@ -165,17 +168,25 @@ static const uint16_t ciphersuite_preference[] =
|
||||||
static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
|
static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && defined(MBEDTLS_AES_C) && defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)
|
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && defined(MBEDTLS_AES_C) && defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
|
||||||
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "ECDHE-ECDSA-AES128-GCM-SHA256",
|
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "ECDHE-ECDSA-AES256-GCM-SHA384",
|
||||||
MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
|
MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
|
||||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||||
0 },
|
0 },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && defined(MBEDTLS_AES_C) && defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)
|
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && defined(MBEDTLS_AES_C) && defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
|
||||||
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "ECDHE-ECDSA-AES256-GCM-SHA384",
|
{ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "ECDHE-RSA-AES256-GCM-SHA384",
|
||||||
MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
|
MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
|
||||||
|
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||||
|
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||||
|
0 },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && defined(MBEDTLS_AES_C) && defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)
|
||||||
|
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "ECDHE-ECDSA-AES128-GCM-SHA256",
|
||||||
|
MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
|
||||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||||
0 },
|
0 },
|
||||||
|
@ -189,9 +200,9 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
|
||||||
0 },
|
0 },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && defined(MBEDTLS_AES_C) && defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)
|
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && defined(MBEDTLS_AES_C) && defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
|
||||||
{ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "ECDHE-RSA-AES256-GCM-SHA384",
|
{ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384, "ECDHE-PSK-AES256-GCM-SHA384",
|
||||||
MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
|
MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
|
||||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||||
0 },
|
0 },
|
||||||
|
@ -267,6 +278,22 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
|
||||||
MBEDTLS_SHA256_C &&
|
MBEDTLS_SHA256_C &&
|
||||||
MBEDTLS_SSL_PROTO_TLS1_2 */
|
MBEDTLS_SSL_PROTO_TLS1_2 */
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && defined(MBEDTLS_AES_C) && defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)
|
||||||
|
{ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, "ECDHE-PSK-AES128-GCM-SHA256",
|
||||||
|
MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
|
||||||
|
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||||
|
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||||
|
0 },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && defined(MBEDTLS_AES_C) && defined(MBEDTLS_CCM_C) && defined(MBEDTLS_SHA512_C)
|
||||||
|
{ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256, "ECDHE-PSK-AES128-CCM-SHA256",
|
||||||
|
MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
|
||||||
|
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||||
|
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||||
|
0 },
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
|
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
|
||||||
#if defined(MBEDTLS_AES_C)
|
#if defined(MBEDTLS_AES_C)
|
||||||
#if defined(MBEDTLS_SHA1_C)
|
#if defined(MBEDTLS_SHA1_C)
|
||||||
|
|
6
third_party/mbedtls/ssl_ciphersuites.h
vendored
6
third_party/mbedtls/ssl_ciphersuites.h
vendored
|
@ -255,6 +255,12 @@ COSMOPOLITAN_C_START_
|
||||||
#define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD /**< TLS 1.2 */
|
#define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD /**< TLS 1.2 */
|
||||||
#define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE /**< TLS 1.2 */
|
#define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE /**< TLS 1.2 */
|
||||||
|
|
||||||
|
/* RFC 8442 */
|
||||||
|
#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 0xD001 /**< TLS 1.2 */
|
||||||
|
#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 0xD002 /**< TLS 1.2 */
|
||||||
|
#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256 0xD003 /**< TLS 1.2 */
|
||||||
|
#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256 0xD005 /**< TLS 1.2 */
|
||||||
|
|
||||||
/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange.
|
/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange.
|
||||||
* Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below
|
* Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below
|
||||||
*/
|
*/
|
||||||
|
|
4
third_party/mbedtls/ssl_tls.c
vendored
4
third_party/mbedtls/ssl_tls.c
vendored
|
@ -4415,8 +4415,8 @@ static int ssl_conf_set_psk_identity( mbedtls_ssl_config *conf,
|
||||||
* \return An \c MBEDTLS_ERR_SSL_XXX error code on failure.
|
* \return An \c MBEDTLS_ERR_SSL_XXX error code on failure.
|
||||||
*/
|
*/
|
||||||
int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
|
int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
|
||||||
const unsigned char *psk, size_t psk_len,
|
const void *psk, size_t psk_len,
|
||||||
const unsigned char *psk_identity,
|
const void *psk_identity,
|
||||||
size_t psk_identity_len )
|
size_t psk_identity_len )
|
||||||
{
|
{
|
||||||
int ret = MBEDTLS_ERR_THIS_CORRUPTION;
|
int ret = MBEDTLS_ERR_THIS_CORRUPTION;
|
||||||
|
|
|
@ -55,6 +55,7 @@ TOOL_BUILD_DIRECTDEPS = \
|
||||||
THIRD_PARTY_GETOPT \
|
THIRD_PARTY_GETOPT \
|
||||||
THIRD_PARTY_STB \
|
THIRD_PARTY_STB \
|
||||||
THIRD_PARTY_XED \
|
THIRD_PARTY_XED \
|
||||||
|
THIRD_PARTY_MBEDTLS \
|
||||||
THIRD_PARTY_ZLIB \
|
THIRD_PARTY_ZLIB \
|
||||||
TOOL_BUILD_LIB
|
TOOL_BUILD_LIB
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,9 @@ struct Command command;
|
||||||
|
|
||||||
const char *const kSafeEnv[] = {
|
const char *const kSafeEnv[] = {
|
||||||
"ADDR2LINE", // needed by GetAddr2linePath
|
"ADDR2LINE", // needed by GetAddr2linePath
|
||||||
|
"HOME", // needed by ~/.runit.psk
|
||||||
|
"HOMEDRIVE", // needed by ~/.runit.psk
|
||||||
|
"HOMEPATH", // needed by ~/.runit.psk
|
||||||
"MAKEFLAGS", // needed by IsRunningUnderMake
|
"MAKEFLAGS", // needed by IsRunningUnderMake
|
||||||
"MODE", // needed by test scripts
|
"MODE", // needed by test scripts
|
||||||
"PATH", // needed by clang
|
"PATH", // needed by clang
|
||||||
|
|
|
@ -46,6 +46,7 @@ TOOL_BUILD_LIB_A_DIRECTDEPS = \
|
||||||
LIBC_UNICODE \
|
LIBC_UNICODE \
|
||||||
LIBC_X \
|
LIBC_X \
|
||||||
THIRD_PARTY_COMPILER_RT \
|
THIRD_PARTY_COMPILER_RT \
|
||||||
|
THIRD_PARTY_MBEDTLS \
|
||||||
THIRD_PARTY_XED
|
THIRD_PARTY_XED
|
||||||
|
|
||||||
TOOL_BUILD_LIB_A_DEPS := \
|
TOOL_BUILD_LIB_A_DEPS := \
|
||||||
|
|
185
tool/build/lib/eztls.c
Normal file
185
tool/build/lib/eztls.c
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/struct/iovec.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/log/check.h"
|
||||||
|
#include "libc/log/log.h"
|
||||||
|
#include "libc/rand/rand.h"
|
||||||
|
#include "libc/sock/sock.h"
|
||||||
|
#include "libc/sysv/consts/sig.h"
|
||||||
|
#include "libc/x/x.h"
|
||||||
|
#include "third_party/mbedtls/ctr_drbg.h"
|
||||||
|
#include "third_party/mbedtls/ecp.h"
|
||||||
|
#include "third_party/mbedtls/error.h"
|
||||||
|
#include "third_party/mbedtls/ssl.h"
|
||||||
|
#include "tool/build/lib/eztls.h"
|
||||||
|
#include "tool/build/lib/psk.h"
|
||||||
|
|
||||||
|
struct EzTlsBio ezbio;
|
||||||
|
mbedtls_ssl_config ezconf;
|
||||||
|
mbedtls_ssl_context ezssl;
|
||||||
|
mbedtls_ctr_drbg_context ezrng;
|
||||||
|
|
||||||
|
static char *EzTlsError(int r) {
|
||||||
|
static char b[128];
|
||||||
|
mbedtls_strerror(r, b, sizeof(b));
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static wontreturn void EzTlsDie(const char *s, int r) {
|
||||||
|
if (IsTiny()) {
|
||||||
|
fprintf(stderr, "error: %s (-0x%04x %s)\n", s, -r, EzTlsError(r));
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "error: %s (grep -0x%04x)\n", s, -r);
|
||||||
|
}
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int EzGetEntropy(void *c, unsigned char *p, size_t n) {
|
||||||
|
CHECK_EQ(n, getrandom(p, n, 0));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EzInitializeRng(mbedtls_ctr_drbg_context *r) {
|
||||||
|
volatile unsigned char b[64];
|
||||||
|
mbedtls_ctr_drbg_init(r);
|
||||||
|
CHECK(getrandom(b, 64, 0) == 64);
|
||||||
|
CHECK(!mbedtls_ctr_drbg_seed(r, EzGetEntropy, 0, b, 64));
|
||||||
|
mbedtls_platform_zeroize(b, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t EzWritevAll(int fd, struct iovec *iov, int iovlen) {
|
||||||
|
int i;
|
||||||
|
ssize_t rc;
|
||||||
|
size_t wrote, total;
|
||||||
|
i = 0;
|
||||||
|
total = 0;
|
||||||
|
do {
|
||||||
|
if (i) {
|
||||||
|
while (i < iovlen && !iov[i].iov_len) ++i;
|
||||||
|
if (i == iovlen) break;
|
||||||
|
}
|
||||||
|
if ((rc = writev(fd, iov + i, iovlen - i)) != -1) {
|
||||||
|
wrote = rc;
|
||||||
|
total += wrote;
|
||||||
|
do {
|
||||||
|
if (wrote >= iov[i].iov_len) {
|
||||||
|
wrote -= iov[i++].iov_len;
|
||||||
|
} else {
|
||||||
|
iov[i].iov_base = (char *)iov[i].iov_base + wrote;
|
||||||
|
iov[i].iov_len -= wrote;
|
||||||
|
wrote = 0;
|
||||||
|
}
|
||||||
|
} while (wrote);
|
||||||
|
} else if (errno != EINTR) {
|
||||||
|
return total ? total : -1;
|
||||||
|
}
|
||||||
|
} while (i < iovlen);
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EzTlsFlush(struct EzTlsBio *bio, const unsigned char *buf, size_t len) {
|
||||||
|
struct iovec v[2];
|
||||||
|
if (len || bio->c > 0) {
|
||||||
|
v[0].iov_base = bio->u;
|
||||||
|
v[0].iov_len = MAX(0, bio->c);
|
||||||
|
v[1].iov_base = buf;
|
||||||
|
v[1].iov_len = len;
|
||||||
|
if (EzWritevAll(bio->fd, v, 2) != -1) {
|
||||||
|
if (bio->c > 0) bio->c = 0;
|
||||||
|
} else if (errno == EINTR) {
|
||||||
|
return MBEDTLS_ERR_NET_CONN_RESET;
|
||||||
|
} else if (errno == EAGAIN) {
|
||||||
|
return MBEDTLS_ERR_SSL_TIMEOUT;
|
||||||
|
} else if (errno == EPIPE || errno == ECONNRESET || errno == ENETRESET) {
|
||||||
|
return MBEDTLS_ERR_NET_CONN_RESET;
|
||||||
|
} else {
|
||||||
|
WARNF("EzTlsSend error %s", strerror(errno));
|
||||||
|
return MBEDTLS_ERR_NET_SEND_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int EzTlsSend(void *ctx, const unsigned char *buf, size_t len) {
|
||||||
|
int rc;
|
||||||
|
struct iovec v[2];
|
||||||
|
struct EzTlsBio *bio = ctx;
|
||||||
|
if (bio->c >= 0 && bio->c + len <= sizeof(bio->u)) {
|
||||||
|
memcpy(bio->u + bio->c, buf, len);
|
||||||
|
bio->c += len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
if ((rc = EzTlsFlush(bio, buf, len)) < 0) return rc;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int EzTlsRecvImpl(void *ctx, unsigned char *p, size_t n, uint32_t o) {
|
||||||
|
int r;
|
||||||
|
ssize_t s;
|
||||||
|
struct iovec v[2];
|
||||||
|
struct EzTlsBio *bio = ctx;
|
||||||
|
if ((r = EzTlsFlush(bio, 0, 0)) < 0) return r;
|
||||||
|
if (bio->a < bio->b) {
|
||||||
|
r = MIN(n, bio->b - bio->a);
|
||||||
|
memcpy(p, bio->t + bio->a, r);
|
||||||
|
if ((bio->a += r) == bio->b) bio->a = bio->b = 0;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
v[0].iov_base = p;
|
||||||
|
v[0].iov_len = n;
|
||||||
|
v[1].iov_base = bio->t;
|
||||||
|
v[1].iov_len = sizeof(bio->t);
|
||||||
|
while ((r = readv(bio->fd, v, 2)) == -1) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
return MBEDTLS_ERR_SSL_WANT_READ;
|
||||||
|
} else if (errno == EAGAIN) {
|
||||||
|
return MBEDTLS_ERR_SSL_TIMEOUT;
|
||||||
|
} else if (errno == EPIPE || errno == ECONNRESET || errno == ENETRESET) {
|
||||||
|
return MBEDTLS_ERR_NET_CONN_RESET;
|
||||||
|
} else {
|
||||||
|
WARNF("tls read() error %s", strerror(errno));
|
||||||
|
return MBEDTLS_ERR_NET_RECV_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (r > n) bio->b = r - n;
|
||||||
|
return MIN(n, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int EzTlsRecv(void *ctx, unsigned char *buf, size_t len, uint32_t tmo) {
|
||||||
|
return EzTlsRecvImpl(ctx, buf, len, tmo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* openssl s_client -connect 127.0.0.1:31337 \
|
||||||
|
* -psk $(hex <~/.runit.psk) \
|
||||||
|
* -psk_identity runit
|
||||||
|
*/
|
||||||
|
|
||||||
|
void SetupPresharedKeySsl(int endpoint) {
|
||||||
|
xsigaction(SIGPIPE, SIG_IGN, 0, 0, 0);
|
||||||
|
EzInitializeRng(&ezrng);
|
||||||
|
mbedtls_ssl_config_defaults(&ezconf, endpoint, MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||||
|
MBEDTLS_SSL_PRESET_SUITEC);
|
||||||
|
mbedtls_ssl_conf_rng(&ezconf, mbedtls_ctr_drbg_random, &ezrng);
|
||||||
|
DCHECK_EQ(0, mbedtls_ssl_conf_psk(&ezconf, GetRunitPsk(), 32, "runit", 5));
|
||||||
|
DCHECK_EQ(0, mbedtls_ssl_setup(&ezssl, &ezconf));
|
||||||
|
mbedtls_ssl_set_bio(&ezssl, &ezbio, EzTlsSend, 0, EzTlsRecv);
|
||||||
|
}
|
25
tool/build/lib/eztls.h
Normal file
25
tool/build/lib/eztls.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_EZTLS_H_
|
||||||
|
#define COSMOPOLITAN_TOOL_BUILD_LIB_EZTLS_H_
|
||||||
|
#include "third_party/mbedtls/ctr_drbg.h"
|
||||||
|
#include "third_party/mbedtls/ssl.h"
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
struct EzTlsBio {
|
||||||
|
int fd, c;
|
||||||
|
unsigned a, b;
|
||||||
|
unsigned char t[4000];
|
||||||
|
unsigned char u[1430];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct EzTlsBio ezbio;
|
||||||
|
extern mbedtls_ssl_config ezconf;
|
||||||
|
extern mbedtls_ssl_context ezssl;
|
||||||
|
extern mbedtls_ctr_drbg_context ezrng;
|
||||||
|
|
||||||
|
void SetupPresharedKeySsl(int);
|
||||||
|
int EzTlsFlush(struct EzTlsBio *, const unsigned char *, size_t);
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_EZTLS_H_ */
|
61
tool/build/lib/psk.c
Normal file
61
tool/build/lib/psk.c
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/struct/stat.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/fmt/fmt.h"
|
||||||
|
#include "libc/log/check.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/sysv/consts/o.h"
|
||||||
|
#include "tool/build/lib/psk.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns preshared key for runit testing infrastructure.
|
||||||
|
*/
|
||||||
|
void *GetRunitPsk(void) {
|
||||||
|
int fd;
|
||||||
|
struct stat st;
|
||||||
|
const char *a, *b;
|
||||||
|
char *r, p[PATH_MAX + 1];
|
||||||
|
if ((a = getenv("HOME"))) {
|
||||||
|
b = "";
|
||||||
|
} else if (IsWindows()) {
|
||||||
|
a = getenv("HOMEDRIVE");
|
||||||
|
b = getenv("HOMEPATH");
|
||||||
|
if (!a || !b) {
|
||||||
|
a = "C:";
|
||||||
|
b = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "need $HOME\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
snprintf(p, sizeof(p), "%s%s/.runit.psk", a, b);
|
||||||
|
if (stat(p, &st) == -1 || st.st_size != 32) {
|
||||||
|
fprintf(stderr, "need o//examples/getrandom.com -bn32 >~/.runit.psk\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
CHECK_NOTNULL((r = malloc(32)));
|
||||||
|
CHECK_NE(-1, (fd = open(p, O_RDONLY)));
|
||||||
|
CHECK_EQ(32, read(fd, r, 32));
|
||||||
|
CHECK_NE(-1, close(fd));
|
||||||
|
return r;
|
||||||
|
}
|
10
tool/build/lib/psk.h
Normal file
10
tool/build/lib/psk.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_PSK_H_
|
||||||
|
#define COSMOPOLITAN_TOOL_BUILD_LIB_PSK_H_
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
void *GetRunitPsk(void);
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_PSK_H_ */
|
|
@ -16,63 +16,55 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/alg/alg.h"
|
|
||||||
#include "libc/bits/bits.h"
|
#include "libc/bits/bits.h"
|
||||||
#include "libc/bits/safemacros.internal.h"
|
#include "libc/bits/safemacros.internal.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/sigbits.h"
|
#include "libc/calls/sigbits.h"
|
||||||
#include "libc/calls/struct/flock.h"
|
#include "libc/calls/struct/flock.h"
|
||||||
#include "libc/calls/struct/itimerval.h"
|
|
||||||
#include "libc/calls/struct/sigaction.h"
|
|
||||||
#include "libc/calls/struct/stat.h"
|
|
||||||
#include "libc/calls/struct/timeval.h"
|
|
||||||
#include "libc/dce.h"
|
|
||||||
#include "libc/dns/dns.h"
|
#include "libc/dns/dns.h"
|
||||||
#include "libc/errno.h"
|
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
#include "libc/fmt/fmt.h"
|
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
#include "libc/log/check.h"
|
#include "libc/log/check.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/runtime/gc.internal.h"
|
#include "libc/runtime/gc.internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
|
||||||
#include "libc/sock/ipclassify.internal.h"
|
#include "libc/sock/ipclassify.internal.h"
|
||||||
#include "libc/sock/sock.h"
|
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
#include "libc/str/str.h"
|
|
||||||
#include "libc/sysv/consts/af.h"
|
#include "libc/sysv/consts/af.h"
|
||||||
#include "libc/sysv/consts/ex.h"
|
#include "libc/sysv/consts/ex.h"
|
||||||
#include "libc/sysv/consts/exit.h"
|
|
||||||
#include "libc/sysv/consts/f.h"
|
|
||||||
#include "libc/sysv/consts/fd.h"
|
|
||||||
#include "libc/sysv/consts/fileno.h"
|
#include "libc/sysv/consts/fileno.h"
|
||||||
#include "libc/sysv/consts/ipproto.h"
|
#include "libc/sysv/consts/ipproto.h"
|
||||||
#include "libc/sysv/consts/itimer.h"
|
#include "libc/sysv/consts/itimer.h"
|
||||||
#include "libc/sysv/consts/lock.h"
|
#include "libc/sysv/consts/lock.h"
|
||||||
|
#include "libc/sysv/consts/map.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/pr.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
#include "libc/sysv/consts/shut.h"
|
|
||||||
#include "libc/sysv/consts/sig.h"
|
|
||||||
#include "libc/sysv/consts/sock.h"
|
#include "libc/sysv/consts/sock.h"
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
#include "libc/x/x.h"
|
#include "libc/x/x.h"
|
||||||
|
#include "third_party/mbedtls/ssl.h"
|
||||||
|
#include "tool/build/lib/eztls.h"
|
||||||
#include "tool/build/runit.h"
|
#include "tool/build/runit.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fileoverview Remote test runner.
|
* @fileoverview Remote test runner.
|
||||||
*
|
*
|
||||||
* This is able to upload and run test binaries on remote operating
|
* We want to scp .com binaries to remote machines and run them. The
|
||||||
* systems with about 30 milliseconds of latency. It requires zero ops
|
* problem is that SSH is the slowest thing imaginable, taking about
|
||||||
* work too, since it deploys the ephemeral runit daemon via SSH upon
|
* 300ms to connect to a host that's merely half a millisecond away.
|
||||||
* ECONNREFUSED. That takes 10x longer (300 milliseconds). Further note
|
*
|
||||||
* there's no make -j race conditions here, thanks to SO_REUSEPORT.
|
* This program takes 17ms using elliptic curve diffie hellman exchange
|
||||||
|
* where we favor a 32-byte binary preshared key (~/.runit.psk) instead
|
||||||
|
* of certificates. It's how long it takes to connect, copy the binary,
|
||||||
|
* and run it. The remote daemon is deployed via SSH if it's not there.
|
||||||
*
|
*
|
||||||
* o/default/tool/build/runit.com \
|
* o/default/tool/build/runit.com \
|
||||||
* o/default/tool/build/runitd.com \
|
* o/default/tool/build/runitd.com \
|
||||||
* o/default/test/libc/alg/qsort_test.com \
|
* o/default/test/libc/alg/qsort_test.com \
|
||||||
* freebsd.test.:31337:22
|
* freebsd.test.:31337:22
|
||||||
*
|
*
|
||||||
|
* APE binaries are hermetic and embed dependent files within their zip
|
||||||
|
* structure, which is why all we need is this simple test runner tool.
|
||||||
* The only thing that needs to be configured is /etc/hosts or Bind, to
|
* The only thing that needs to be configured is /etc/hosts or Bind, to
|
||||||
* assign numbers to the officially reserved canned names. For example:
|
* assign numbers to the officially reserved canned names. For example:
|
||||||
*
|
*
|
||||||
|
@ -97,12 +89,7 @@
|
||||||
* iptables -I INPUT 1 -s 10.0.0.0/8 -p tcp --dport 31337 -j ACCEPT
|
* iptables -I INPUT 1 -s 10.0.0.0/8 -p tcp --dport 31337 -j ACCEPT
|
||||||
* iptables -I INPUT 1 -s 192.168.0.0/16 -p tcp --dport 31337 -j ACCEPT
|
* iptables -I INPUT 1 -s 192.168.0.0/16 -p tcp --dport 31337 -j ACCEPT
|
||||||
*
|
*
|
||||||
* If your system administrator blocks all ICMP, you'll likely encounter
|
* This tool may be used in zero trust environments.
|
||||||
* difficulties. Consider offering feedback to his/her manager and grand
|
|
||||||
* manager.
|
|
||||||
*
|
|
||||||
* Finally note this tool isn't designed for untrustworthy environments.
|
|
||||||
* It also isn't designed to process untrustworthy inputs.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const struct addrinfo kResolvHints = {.ai_family = AF_INET,
|
static const struct addrinfo kResolvHints = {.ai_family = AF_INET,
|
||||||
|
@ -301,7 +288,9 @@ TryAgain:
|
||||||
|
|
||||||
void SendRequest(void) {
|
void SendRequest(void) {
|
||||||
int fd;
|
int fd;
|
||||||
int64_t off;
|
char *p;
|
||||||
|
size_t i;
|
||||||
|
ssize_t rc;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned char *hdr;
|
unsigned char *hdr;
|
||||||
|
@ -309,6 +298,7 @@ void SendRequest(void) {
|
||||||
DEBUGF("running %s on %s", g_prog, g_hostname);
|
DEBUGF("running %s on %s", g_prog, g_hostname);
|
||||||
CHECK_NE(-1, (fd = open(g_prog, O_RDONLY)));
|
CHECK_NE(-1, (fd = open(g_prog, O_RDONLY)));
|
||||||
CHECK_NE(-1, fstat(fd, &st));
|
CHECK_NE(-1, fstat(fd, &st));
|
||||||
|
CHECK_NE(MAP_FAILED, (p = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0)));
|
||||||
CHECK_LE((namesize = strlen((name = basename(g_prog)))), PATH_MAX);
|
CHECK_LE((namesize = strlen((name = basename(g_prog)))), PATH_MAX);
|
||||||
CHECK_LE((progsize = st.st_size), INT_MAX);
|
CHECK_LE((progsize = st.st_size), INT_MAX);
|
||||||
CHECK_NOTNULL((hdr = gc(calloc(1, (hdrsize = 4 + 1 + 4 + 4 + namesize)))));
|
CHECK_NOTNULL((hdr = gc(calloc(1, (hdrsize = 4 + 1 + 4 + 4 + namesize)))));
|
||||||
|
@ -326,25 +316,27 @@ void SendRequest(void) {
|
||||||
hdr[9 + 2] = (unsigned char)((unsigned)progsize >> 010);
|
hdr[9 + 2] = (unsigned char)((unsigned)progsize >> 010);
|
||||||
hdr[9 + 3] = (unsigned char)((unsigned)progsize >> 000);
|
hdr[9 + 3] = (unsigned char)((unsigned)progsize >> 000);
|
||||||
memcpy(&hdr[4 + 1 + 4 + 4], name, namesize);
|
memcpy(&hdr[4 + 1 + 4 + 4], name, namesize);
|
||||||
CHECK_EQ(hdrsize, write(g_sock, hdr, hdrsize));
|
CHECK_EQ(hdrsize, mbedtls_ssl_write(&ezssl, hdr, hdrsize));
|
||||||
for (off = 0; off < progsize;) {
|
for (i = 0; i < progsize; i += rc) {
|
||||||
CHECK_GT(sendfile(g_sock, fd, &off, progsize - off), 0);
|
CHECK_GT((rc = mbedtls_ssl_write(&ezssl, p + i, progsize - i)), 0);
|
||||||
}
|
}
|
||||||
CHECK_NE(-1, shutdown(g_sock, SHUT_WR));
|
CHECK_NE(-1, EzTlsFlush(&ezbio, 0, 0));
|
||||||
|
CHECK_NE(-1, munmap(p, st.st_size));
|
||||||
|
CHECK_NE(-1, close(fd));
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadResponse(void) {
|
int ReadResponse(void) {
|
||||||
int res;
|
int res;
|
||||||
uint32_t size;
|
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
size_t n, m;
|
size_t n, m;
|
||||||
|
uint32_t size;
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
enum RunitCommand cmd;
|
enum RunitCommand cmd;
|
||||||
static long backoff;
|
static long backoff;
|
||||||
static unsigned char msg[512];
|
static unsigned char msg[512];
|
||||||
res = -1;
|
res = -1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((rc = recv(g_sock, msg, sizeof(msg), 0)) == -1) {
|
if ((rc = mbedtls_ssl_read(&ezssl, msg, sizeof(msg))) == -1) {
|
||||||
CHECK_EQ(ECONNRESET, errno);
|
CHECK_EQ(ECONNRESET, errno);
|
||||||
usleep((backoff = (backoff + 1000) * 2));
|
usleep((backoff = (backoff + 1000) * 2));
|
||||||
break;
|
break;
|
||||||
|
@ -369,7 +361,7 @@ int ReadResponse(void) {
|
||||||
size = READ32BE(p), p += 4, n -= 4;
|
size = READ32BE(p), p += 4, n -= 4;
|
||||||
while (size) {
|
while (size) {
|
||||||
if (n) {
|
if (n) {
|
||||||
CHECK_NE(-1, (rc = write(STDERR_FILENO, p, min(n, size))));
|
CHECK_NE(-1, (rc = write(STDERR_FILENO, p, MIN(n, size))));
|
||||||
CHECK_NE(0, (m = (size_t)rc));
|
CHECK_NE(0, (m = (size_t)rc));
|
||||||
p += m, n -= m, size -= m;
|
p += m, n -= m, size -= m;
|
||||||
} else {
|
} else {
|
||||||
|
@ -400,7 +392,11 @@ int RunOnHost(char *spec) {
|
||||||
1);
|
1);
|
||||||
if (!strchr(g_hostname, '.')) strcat(g_hostname, ".test.");
|
if (!strchr(g_hostname, '.')) strcat(g_hostname, ".test.");
|
||||||
do {
|
do {
|
||||||
|
mbedtls_ssl_session_reset(&ezssl);
|
||||||
Connect();
|
Connect();
|
||||||
|
ezbio.fd = g_sock;
|
||||||
|
CHECK_EQ(0, mbedtls_ssl_handshake(&ezssl));
|
||||||
|
CHECK_NE(-1, EzTlsFlush(&ezbio, 0, 0));
|
||||||
SendRequest();
|
SendRequest();
|
||||||
} while ((rc = ReadResponse()) == -1);
|
} while ((rc = ReadResponse()) == -1);
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -464,6 +460,7 @@ int RunRemoteTestsInParallel(char *hosts[], int count) {
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
showcrashreports();
|
showcrashreports();
|
||||||
|
SetupPresharedKeySsl(MBEDTLS_SSL_IS_CLIENT);
|
||||||
/* __log_level = kLogDebug; */
|
/* __log_level = kLogDebug; */
|
||||||
if (argc > 1 &&
|
if (argc > 1 &&
|
||||||
(strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)) {
|
(strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)) {
|
||||||
|
|
|
@ -17,49 +17,37 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/bits/bits.h"
|
#include "libc/bits/bits.h"
|
||||||
#include "libc/bits/safemacros.internal.h"
|
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/sigbits.h"
|
#include "libc/calls/sigbits.h"
|
||||||
#include "libc/calls/struct/sigaction.h"
|
|
||||||
#include "libc/calls/struct/stat.h"
|
|
||||||
#include "libc/dce.h"
|
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
#include "libc/fmt/fmt.h"
|
|
||||||
#include "libc/log/check.h"
|
#include "libc/log/check.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/macros.internal.h"
|
|
||||||
#include "libc/nt/runtime.h"
|
|
||||||
#include "libc/paths.h"
|
|
||||||
#include "libc/runtime/gc.internal.h"
|
#include "libc/runtime/gc.internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
#include "libc/stdio/temp.h"
|
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/af.h"
|
#include "libc/sysv/consts/af.h"
|
||||||
#include "libc/sysv/consts/auxv.h"
|
|
||||||
#include "libc/sysv/consts/ex.h"
|
#include "libc/sysv/consts/ex.h"
|
||||||
#include "libc/sysv/consts/exit.h"
|
#include "libc/sysv/consts/exit.h"
|
||||||
#include "libc/sysv/consts/f.h"
|
#include "libc/sysv/consts/f.h"
|
||||||
#include "libc/sysv/consts/fd.h"
|
#include "libc/sysv/consts/fd.h"
|
||||||
#include "libc/sysv/consts/fileno.h"
|
|
||||||
#include "libc/sysv/consts/inaddr.h"
|
#include "libc/sysv/consts/inaddr.h"
|
||||||
#include "libc/sysv/consts/ipproto.h"
|
#include "libc/sysv/consts/ipproto.h"
|
||||||
#include "libc/sysv/consts/itimer.h"
|
#include "libc/sysv/consts/itimer.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/poll.h"
|
#include "libc/sysv/consts/poll.h"
|
||||||
#include "libc/sysv/consts/sa.h"
|
#include "libc/sysv/consts/sa.h"
|
||||||
#include "libc/sysv/consts/shut.h"
|
|
||||||
#include "libc/sysv/consts/sig.h"
|
|
||||||
#include "libc/sysv/consts/so.h"
|
#include "libc/sysv/consts/so.h"
|
||||||
#include "libc/sysv/consts/sock.h"
|
#include "libc/sysv/consts/sock.h"
|
||||||
#include "libc/sysv/consts/sol.h"
|
#include "libc/sysv/consts/sol.h"
|
||||||
#include "libc/sysv/consts/w.h"
|
#include "libc/sysv/consts/w.h"
|
||||||
#include "libc/testlib/testlib.h"
|
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
#include "libc/x/x.h"
|
#include "libc/x/x.h"
|
||||||
#include "third_party/getopt/getopt.h"
|
#include "third_party/getopt/getopt.h"
|
||||||
|
#include "third_party/mbedtls/ssl.h"
|
||||||
|
#include "tool/build/lib/eztls.h"
|
||||||
#include "tool/build/runit.h"
|
#include "tool/build/runit.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -208,7 +196,7 @@ void StartTcpServer(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendExitMessage(int sock, int rc) {
|
void SendExitMessage(int rc) {
|
||||||
unsigned char msg[4 + 1 + 1];
|
unsigned char msg[4 + 1 + 1];
|
||||||
msg[0 + 0] = (unsigned char)((unsigned)RUNITD_MAGIC >> 030);
|
msg[0 + 0] = (unsigned char)((unsigned)RUNITD_MAGIC >> 030);
|
||||||
msg[0 + 1] = (unsigned char)((unsigned)RUNITD_MAGIC >> 020);
|
msg[0 + 1] = (unsigned char)((unsigned)RUNITD_MAGIC >> 020);
|
||||||
|
@ -216,11 +204,12 @@ void SendExitMessage(int sock, int rc) {
|
||||||
msg[0 + 3] = (unsigned char)((unsigned)RUNITD_MAGIC >> 000);
|
msg[0 + 3] = (unsigned char)((unsigned)RUNITD_MAGIC >> 000);
|
||||||
msg[4] = kRunitExit;
|
msg[4] = kRunitExit;
|
||||||
msg[5] = (unsigned char)rc;
|
msg[5] = (unsigned char)rc;
|
||||||
CHECK_EQ(sizeof(msg), send(sock, msg, sizeof(msg), 0));
|
CHECK_EQ(sizeof(msg), mbedtls_ssl_write(&ezssl, msg, sizeof(msg)));
|
||||||
|
CHECK_NE(-1, EzTlsFlush(&ezbio, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendOutputFragmentMessage(int sock, enum RunitCommand kind,
|
void SendOutputFragmentMessage(enum RunitCommand kind, unsigned char *buf,
|
||||||
unsigned char *buf, size_t size) {
|
size_t size) {
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
size_t sent;
|
size_t sent;
|
||||||
unsigned char msg[4 + 1 + 4];
|
unsigned char msg[4 + 1 + 4];
|
||||||
|
@ -233,13 +222,14 @@ void SendOutputFragmentMessage(int sock, enum RunitCommand kind,
|
||||||
msg[5 + 1] = (unsigned char)((unsigned)size >> 020);
|
msg[5 + 1] = (unsigned char)((unsigned)size >> 020);
|
||||||
msg[5 + 2] = (unsigned char)((unsigned)size >> 010);
|
msg[5 + 2] = (unsigned char)((unsigned)size >> 010);
|
||||||
msg[5 + 3] = (unsigned char)((unsigned)size >> 000);
|
msg[5 + 3] = (unsigned char)((unsigned)size >> 000);
|
||||||
CHECK_EQ(sizeof(msg), send(sock, msg, sizeof(msg), 0));
|
CHECK_EQ(sizeof(msg), mbedtls_ssl_write(&ezssl, msg, sizeof(msg)));
|
||||||
while (size) {
|
while (size) {
|
||||||
CHECK_NE(-1, (rc = send(sock, buf, size, 0)));
|
CHECK_NE(-1, (rc = mbedtls_ssl_write(&ezssl, buf, size)));
|
||||||
CHECK_LE((sent = (size_t)rc), size);
|
CHECK_LE((sent = (size_t)rc), size);
|
||||||
size -= sent;
|
size -= sent;
|
||||||
buf += sent;
|
buf += sent;
|
||||||
}
|
}
|
||||||
|
CHECK_NE(-1, EzTlsFlush(&ezbio, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnAlarm(int sig) {
|
void OnAlarm(int sig) {
|
||||||
|
@ -274,9 +264,12 @@ void HandleClient(void) {
|
||||||
close(g_clifd);
|
close(g_clifd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ezbio.fd = g_clifd;
|
||||||
|
CHECK_EQ(0, mbedtls_ssl_handshake(&ezssl));
|
||||||
|
CHECK_NE(-1, EzTlsFlush(&ezbio, 0, 0));
|
||||||
addrstr = gc(DescribeAddress(&addr));
|
addrstr = gc(DescribeAddress(&addr));
|
||||||
DEBUGF("%s %s %s", gc(DescribeAddress(&g_servaddr)), "accepted", addrstr);
|
DEBUGF("%s %s %s", gc(DescribeAddress(&g_servaddr)), "accepted", addrstr);
|
||||||
got = recv(g_clifd, (p = &g_buf[0]), sizeof(g_buf), 0);
|
got = mbedtls_ssl_read(&ezssl, (p = &g_buf[0]), sizeof(g_buf));
|
||||||
CHECK_GE(got, kMinMsgSize);
|
CHECK_GE(got, kMinMsgSize);
|
||||||
CHECK_LE(got, sizeof(g_buf));
|
CHECK_LE(got, sizeof(g_buf));
|
||||||
CHECK_EQ(RUNITD_MAGIC, READ32BE(p));
|
CHECK_EQ(RUNITD_MAGIC, READ32BE(p));
|
||||||
|
@ -304,7 +297,7 @@ void HandleClient(void) {
|
||||||
remaining -= got;
|
remaining -= got;
|
||||||
}
|
}
|
||||||
while (remaining) {
|
while (remaining) {
|
||||||
CHECK_NE(-1, (got = recv(g_clifd, g_buf, sizeof(g_buf), 0)));
|
CHECK_NE(-1, (got = mbedtls_ssl_read(&ezssl, g_buf, sizeof(g_buf))));
|
||||||
CHECK_LE(got, remaining);
|
CHECK_LE(got, remaining);
|
||||||
if (!got) {
|
if (!got) {
|
||||||
LOGF("%s %s %,u/%,u %s", addrstr, "sent", remaining, filesize,
|
LOGF("%s %s %,u/%,u %s", addrstr, "sent", remaining, filesize,
|
||||||
|
@ -351,7 +344,7 @@ void HandleClient(void) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fwrite(g_buf, got, 1, stderr);
|
fwrite(g_buf, got, 1, stderr);
|
||||||
SendOutputFragmentMessage(g_clifd, kRunitStderr, g_buf, got);
|
SendOutputFragmentMessage(kRunitStderr, g_buf, got);
|
||||||
} else {
|
} else {
|
||||||
CHECK_EQ(EINTR, errno);
|
CHECK_EQ(EINTR, errno);
|
||||||
}
|
}
|
||||||
|
@ -381,7 +374,8 @@ void HandleClient(void) {
|
||||||
|
|
||||||
/* let client know how it went */
|
/* let client know how it went */
|
||||||
LOGIFNEG1(unlink(g_exepath));
|
LOGIFNEG1(unlink(g_exepath));
|
||||||
SendExitMessage(g_clifd, exitcode);
|
SendExitMessage(exitcode);
|
||||||
|
mbedtls_ssl_close_notify(&ezssl);
|
||||||
LOGIFNEG1(close(g_clifd));
|
LOGIFNEG1(close(g_clifd));
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
@ -442,6 +436,7 @@ void Daemonize(void) {
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
showcrashreports();
|
showcrashreports();
|
||||||
|
SetupPresharedKeySsl(MBEDTLS_SSL_IS_SERVER);
|
||||||
/* __log_level = kLogDebug; */
|
/* __log_level = kLogDebug; */
|
||||||
GetOpts(argc, argv);
|
GetOpts(argc, argv);
|
||||||
CHECK_NE(-1, (g_devnullfd = open("/dev/null", O_RDWR)));
|
CHECK_NE(-1, (g_devnullfd = open("/dev/null", O_RDWR)));
|
||||||
|
|
|
@ -639,6 +639,9 @@ FUNCTIONS
|
||||||
Returns host associated with request. This will be the Host
|
Returns host associated with request. This will be the Host
|
||||||
header, if it's supplied. Otherwise it's the bind address.
|
header, if it's supplied. Otherwise it's the bind address.
|
||||||
|
|
||||||
|
GetHostOs() → str
|
||||||
|
Returns string that describes the host OS.
|
||||||
|
|
||||||
GetMonospaceWidth(str|char) → int
|
GetMonospaceWidth(str|char) → int
|
||||||
Returns monospace display width of string. This is useful for
|
Returns monospace display width of string. This is useful for
|
||||||
fixed-width formatting. For example, CJK characters typically take
|
fixed-width formatting. For example, CJK characters typically take
|
||||||
|
@ -1101,6 +1104,8 @@ CONSTANTS
|
||||||
|
|
||||||
kLogFatal
|
kLogFatal
|
||||||
Integer for fatal logging level, which is less than kLogError.
|
Integer for fatal logging level, which is less than kLogError.
|
||||||
|
Logging anything at this level will result in a backtrace and
|
||||||
|
process exit.
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
|
|
||||||
|
|
|
@ -4911,7 +4911,7 @@ static int LuaLog(lua_State *L) {
|
||||||
level = luaL_checkinteger(L, 1);
|
level = luaL_checkinteger(L, 1);
|
||||||
if (LOGGABLE(level)) {
|
if (LOGGABLE(level)) {
|
||||||
msg = luaL_checkstring(L, 2);
|
msg = luaL_checkstring(L, 2);
|
||||||
lua_getstack(L, 1, &ar);
|
lua_getstack(L, 0, &ar);
|
||||||
lua_getinfo(L, "nSl", &ar);
|
lua_getinfo(L, "nSl", &ar);
|
||||||
if (!strcmp(ar.name, "main")) {
|
if (!strcmp(ar.name, "main")) {
|
||||||
module = strndup(effectivepath.p, effectivepath.n);
|
module = strndup(effectivepath.p, effectivepath.n);
|
||||||
|
@ -5035,6 +5035,32 @@ static int LuaGetComment(lua_State *L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int LuaGetHostOs(lua_State *L) {
|
||||||
|
const char *s = NULL;
|
||||||
|
if (IsLinux()) {
|
||||||
|
s = "LINUX";
|
||||||
|
} else if (IsMetal()) {
|
||||||
|
s = "METAL";
|
||||||
|
} else if (IsWindows()) {
|
||||||
|
s = "WINDOWS";
|
||||||
|
} else if (IsXnu()) {
|
||||||
|
s = "XNU";
|
||||||
|
} else if (IsOpenbsd()) {
|
||||||
|
s = "OPENBSD";
|
||||||
|
} else if (IsFreebsd()) {
|
||||||
|
s = "FREEBSD";
|
||||||
|
} else if (IsNetbsd()) {
|
||||||
|
s = "NETBSD";
|
||||||
|
}
|
||||||
|
if (s) {
|
||||||
|
lua_pushstring(L, s);
|
||||||
|
} else {
|
||||||
|
lua_pushnil(L);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void LuaSetIntField(lua_State *L, const char *k, lua_Integer v) {
|
static void LuaSetIntField(lua_State *L, const char *k, lua_Integer v) {
|
||||||
lua_pushinteger(L, v);
|
lua_pushinteger(L, v);
|
||||||
lua_setfield(L, -2, k);
|
lua_setfield(L, -2, k);
|
||||||
|
@ -5194,6 +5220,7 @@ static bool LuaRun(const char *path, bool mandatory) {
|
||||||
} else {
|
} else {
|
||||||
WARNF("%s %s", path, lua_tostring(L, -1));
|
WARNF("%s %s", path, lua_tostring(L, -1));
|
||||||
}
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
free(code);
|
free(code);
|
||||||
}
|
}
|
||||||
|
@ -5236,6 +5263,7 @@ static const luaL_Reg kLuaFuncs[] = {
|
||||||
{"GetHeader", LuaGetHeader}, //
|
{"GetHeader", LuaGetHeader}, //
|
||||||
{"GetHeaders", LuaGetHeaders}, //
|
{"GetHeaders", LuaGetHeaders}, //
|
||||||
{"GetHost", LuaGetHost}, //
|
{"GetHost", LuaGetHost}, //
|
||||||
|
{"GetHostOs", LuaGetHostOs}, //
|
||||||
{"GetHttpReason", LuaGetHttpReason}, //
|
{"GetHttpReason", LuaGetHttpReason}, //
|
||||||
{"GetHttpVersion", LuaGetHttpVersion}, //
|
{"GetHttpVersion", LuaGetHttpVersion}, //
|
||||||
{"GetLastModifiedTime", LuaGetLastModifiedTime}, //
|
{"GetLastModifiedTime", LuaGetLastModifiedTime}, //
|
||||||
|
|
|
@ -18,75 +18,30 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/fmt.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
|
#include "libc/stdio/append.internal.h"
|
||||||
|
#include "libc/stdio/hex.internal.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
|
|
||||||
struct Append {
|
/**
|
||||||
size_t i, n;
|
* @fileoverview Hex String Literal Converter, e.g.
|
||||||
char *p;
|
*
|
||||||
};
|
* $ echo hello | o/tool/viz/dumphexc.com
|
||||||
|
* "\
|
||||||
int AppendFmt(struct Append *b, const char *fmt, ...) {
|
* \x68\x65\x6c\x6c\x6f\x0a"
|
||||||
int n;
|
*/
|
||||||
char *p;
|
|
||||||
va_list va, vb;
|
|
||||||
va_start(va, fmt);
|
|
||||||
va_copy(vb, va);
|
|
||||||
n = vsnprintf(b->p + b->i, b->n - b->i, fmt, va);
|
|
||||||
if (n >= b->n - b->i) {
|
|
||||||
do {
|
|
||||||
if (b->n) {
|
|
||||||
b->n += b->n >> 1; /* this is the important line */
|
|
||||||
} else {
|
|
||||||
b->n = 16;
|
|
||||||
}
|
|
||||||
} while (b->i + n + 1 > b->n);
|
|
||||||
b->p = realloc(b->p, b->n);
|
|
||||||
vsnprintf(b->p + b->i, b->n - b->i, fmt, vb);
|
|
||||||
}
|
|
||||||
va_end(vb);
|
|
||||||
va_end(va);
|
|
||||||
b->i += n;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *DumpHexc(const char *data, size_t size, size_t *z) {
|
|
||||||
long o;
|
|
||||||
int b, i, n;
|
|
||||||
char A[128], *p;
|
|
||||||
struct Append buf;
|
|
||||||
if (size == -1) size = data ? strlen(data) : 0;
|
|
||||||
buf.i = 0;
|
|
||||||
buf.n = 256;
|
|
||||||
buf.p = calloc(1, 256);
|
|
||||||
AppendFmt(&buf, "\"\\\n");
|
|
||||||
for (b = o = 0; (n = MIN(16, size)); data += n, size -= n) {
|
|
||||||
p = A;
|
|
||||||
for (i = 0; i < n; ++i) {
|
|
||||||
*p++ = '\\';
|
|
||||||
*p++ = 'x';
|
|
||||||
*p++ = "0123456789abcdef"[(data[i] & 0xF0) >> 4];
|
|
||||||
*p++ = "0123456789abcdef"[(data[i] & 0x0F) >> 0];
|
|
||||||
}
|
|
||||||
if (o) AppendFmt(&buf, "\\\n");
|
|
||||||
AppendFmt(&buf, "%.*s", p - A, A);
|
|
||||||
o += n;
|
|
||||||
}
|
|
||||||
AppendFmt(&buf, "\"");
|
|
||||||
if (z) *z = buf.i;
|
|
||||||
return buf.p;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
char *p;
|
char *p;
|
||||||
size_t n, g;
|
size_t n, g;
|
||||||
|
char *b = 0;
|
||||||
char buf[512];
|
char buf[512];
|
||||||
struct Append b = {0};
|
|
||||||
while ((g = fread(buf, 1, sizeof(buf), stdin))) {
|
while ((g = fread(buf, 1, sizeof(buf), stdin))) {
|
||||||
AppendFmt(&b, "%.*s", g, buf);
|
appendd(&b, buf, g);
|
||||||
}
|
}
|
||||||
if (!ferror(stdin)) {
|
if (!ferror(stdin)) {
|
||||||
p = DumpHexc(b.p, b.i, &n);
|
p = DumpHexc(b, appendz(b).i, &n);
|
||||||
fwrite(p, 1, n, stdout);
|
fwrite(p, 1, n, stdout);
|
||||||
|
free(p);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
return ferror(stdin) || ferror(stdout) ? 1 : 0;
|
return ferror(stdin) || ferror(stdout) ? 1 : 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue