Fix bugs and make improvements to redbean

- Abort if .init.lua fails
- Refactor redbean to use new append library
- Use first certificate if SNI routing fails
- Use function/data sections when building Lua
- Don't use self-signed auto-generated cert for client
- Add -D staging dirs to redbean lua module default path
This commit is contained in:
Justine Tunney 2021-08-06 14:12:11 -07:00
parent 55a15c204e
commit aeeb851422
26 changed files with 703 additions and 513 deletions

View file

@ -44,9 +44,10 @@ double MeasureEntropy(const char *p, size_t n) {
if (h[i]) { if (h[i]) {
x = h[i]; x = h[i];
x /= n; x /= n;
e += x * log2(1 / x); e += x * log(x);
} }
} }
e = -(e / M_LN2);
} }
return e; return e;
} }

View file

@ -32,16 +32,18 @@ struct MemoryIntervals {
} p[128]; } p[128];
}; };
extern struct MemoryIntervals _mmi; extern hidden struct MemoryIntervals _mmi;
unsigned FindMemoryInterval(const struct MemoryIntervals *, int) nosideeffect; unsigned FindMemoryInterval(const struct MemoryIntervals *,
bool AreMemoryIntervalsOk(const struct MemoryIntervals *) nosideeffect; int) nosideeffect hidden;
void PrintMemoryIntervals(int, const struct MemoryIntervals *); bool AreMemoryIntervalsOk(const struct MemoryIntervals *) nosideeffect hidden;
int TrackMemoryInterval(struct MemoryIntervals *, int, int, long, int, int); void PrintMemoryIntervals(int, const struct MemoryIntervals *) hidden;
int TrackMemoryInterval(struct MemoryIntervals *, int, int, long, int,
int) hidden;
int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int, int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int,
void (*)(struct MemoryIntervals *, int, int)); void (*)(struct MemoryIntervals *, int, int)) hidden;
void ReleaseMemoryNt(struct MemoryIntervals *, int, int); void ReleaseMemoryNt(struct MemoryIntervals *, int, int) hidden;
int UntrackMemoryIntervals(void *, size_t); int UntrackMemoryIntervals(void *, size_t) hidden;
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -1,5 +1,5 @@
#ifndef COSMOPOLITAN_LIBC_STDIO_APPEND_INTERNAL_H_ #ifndef COSMOPOLITAN_LIBC_STDIO_APPEND_H_
#define COSMOPOLITAN_LIBC_STDIO_APPEND_INTERNAL_H_ #define COSMOPOLITAN_LIBC_STDIO_APPEND_H_
#include "libc/fmt/pflink.h" #include "libc/fmt/pflink.h"
#define APPEND_COOKIE 21578 #define APPEND_COOKIE 21578
@ -8,22 +8,23 @@
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
struct appendz { struct appendz {
size_t i; /* data size */ size_t i;
size_t n; /* allocation size */ size_t n;
}; };
int appendf(char **, const char *, ...);
int vappendf(char **, const char *, va_list);
int appends(char **, const char *);
int appendd(char **, const void *, size_t);
int appendw(char **, uint64_t);
struct appendz appendz(char *); struct appendz appendz(char *);
ssize_t appendr(char **, size_t);
ssize_t appendd(char **, const void *, size_t);
ssize_t appendw(char **, uint64_t);
ssize_t appends(char **, const char *);
ssize_t appendf(char **, const char *, ...);
ssize_t vappendf(char **, const char *, va_list);
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define appendf(BUF, FMT, ...) (appendf)(BUF, PFLINK(FMT), ##__VA_ARGS__) #define appendf(BUF, FMT, ...) appendf(BUF, PFLINK(FMT), ##__VA_ARGS__)
#define vappendf(BUF, FMT, VA) (vappendf)(BUF, PFLINK(FMT), VA) #define vappendf(BUF, FMT, VA) vappendf(BUF, PFLINK(FMT), VA)
#endif #endif
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_STDIO_APPEND_INTERNAL_H_ */ #endif /* COSMOPOLITAN_LIBC_STDIO_APPEND_H_ */

View file

@ -26,11 +26,24 @@
#define W sizeof(size_t) #define W sizeof(size_t)
/** /**
* Appends raw data to buffer. * Appends data to buffer, e.g.
*
* char *b = 0;
* appendd(&b, "hello", 5);
* free(b);
*
* The resulting buffer is guaranteed to be NUL-terminated, i.e.
* `!b[appendz(b).i]` will be the case.
*
* @param s may contain nul characters and may be null if `l` is zero
* @param l is byte length of `s`
* @return bytes appended (always `l`) or -1 if `ENOMEM`
* @see appendz(b).i to get buffer length
*/ */
int appendd(char **b, const void *s, size_t l) { ssize_t appendd(char **b, const void *s, size_t l) {
char *p; char *p;
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) { if (ROUNDUP(z.i + l + 1, 8) + W > z.n) {
if (!z.n) z.n = W * 2; if (!z.n) z.n = W * 2;

View file

@ -19,9 +19,16 @@
#include "libc/stdio/append.internal.h" #include "libc/stdio/append.internal.h"
/** /**
* Appends formatted data to buffer. * Appends formatted string to buffer, e.g.
*
* char *b = 0;
* appendf(&b, "hello %d\n", 123);
* free(b);
*
* @return bytes appended or -1 if `ENOMEM`
* @see appendz(b).i to get buffer length
*/ */
int(appendf)(char **b, const char *fmt, ...) { ssize_t(appendf)(char **b, const char *fmt, ...) {
int n; int n;
va_list va; va_list va;
va_start(va, fmt); va_start(va, fmt);

71
libc/stdio/appendr.c Normal file
View file

@ -0,0 +1,71 @@
/*-*- 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/assert.h"
#include "libc/dce.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/stdio/append.internal.h"
#include "libc/str/str.h"
#define W sizeof(size_t)
/**
* Resets length of append buffer, e.g.
*
* char *b = 0;
* appends(&b, "hello");
* appendr(&b, 1);
* assert(!strcmp(b, "h"));
* appendr(&b, 0);
* assert(!strcmp(b, ""));
* free(b);
*
* If `i` is greater than the current length then the extra bytes are
* filled with NUL characters.
*
* The resulting buffer is guarranteed to be NUL-terminated, i.e.
* `!b[appendz(b).i]` will be the case.
*
* @return `i` or -1 if `ENOMEM`
* @see appendz(b).i to get buffer length
*/
ssize_t appendr(char **b, size_t i) {
char *p;
struct appendz z;
assert(b);
z = appendz((p = *b));
z.n = ROUNDUP(i + 1, 8) + W;
if ((p = realloc(p, z.n))) {
z.n = malloc_usable_size(p);
assert(!(z.n & (W - 1)));
*b = p;
} else {
return -1;
}
if (i > z.i) {
memset(p, z.i, i - z.i);
}
z.i = i;
p[z.i] = 0;
if (!IsTiny() && W == 8) {
z.i |= (size_t)APPEND_COOKIE << 48;
}
*(size_t *)(p + z.n - W) = z.i;
return i;
}

View file

@ -20,8 +20,18 @@
#include "libc/str/str.h" #include "libc/str/str.h"
/** /**
* Appends string to buffer. * Appends string to buffer, e.g.
*
* char *b = 0;
* appends(&b, "hello");
* free(b);
*
* The resulting buffer is guaranteed to be NUL-terminated, i.e.
* `!b[appendz(b).i]` will be the case.
*
* @return bytes appended (always `strlen(s)`) or -1 if `ENOMEM`
* @see appendz(b).i to get buffer length
*/ */
int 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));
} }

View file

@ -19,15 +19,33 @@
#include "libc/bits/bits.h" #include "libc/bits/bits.h"
#include "libc/nexgen32e/bsr.h" #include "libc/nexgen32e/bsr.h"
#include "libc/stdio/append.internal.h" #include "libc/stdio/append.internal.h"
#include "libc/stdio/stdio.h"
/** /**
* Appends string to buffer. * Appends character or word-encoded string to buffer.
*
* Up to eight characters can be appended. For example:
*
* appendw(&s, 'h'|'i'<<8);
*
* Is equivalent to:
*
* appends(&s, "hi");
*
* The special case:
*
* appendw(&s, 0);
*
* Will append a single NUL character.
*
* The resulting buffer is guaranteed to be NUL-terminated, i.e.
* `!b[appendz(b).i]` will be the case.
*
* @return bytes appended or -1 if `ENOMEM`
*/ */
int appendw(char **b, uint64_t w) { ssize_t appendw(char **b, uint64_t w) {
char t[8]; char t[8];
unsigned l; unsigned n = 1;
if (!w) return 0;
WRITE64LE(t, w); WRITE64LE(t, w);
return appendd(b, t, (bsrl(w) >> 3) + 1); if (w) n += bsrl(w) >> 3;
return appendd(b, t, n);
} }

View file

@ -25,6 +25,9 @@
/** /**
* Returns size of append buffer. * Returns size of append buffer.
*
* @return i is number of bytes stored in buffer
* @return n is number of bytes in allocation
*/ */
struct appendz appendz(char *p) { struct appendz appendz(char *p) {
struct appendz z; struct appendz z;

View file

@ -55,6 +55,10 @@ o/$(MODE)/libc/stdio/fputc.o: \
OVERRIDE_CFLAGS += \ OVERRIDE_CFLAGS += \
-O3 -O3
o//libc/stdio/appendw.o: \
OVERRIDE_CFLAGS += \
-O2
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))
LIBC_STDIO_HDRS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_HDRS)) LIBC_STDIO_HDRS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_HDRS))

View file

@ -25,9 +25,9 @@
#define W sizeof(size_t) #define W sizeof(size_t)
/** /**
* Appends data to buffer. * Appends formatted string to buffer.
*/ */
int(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;
va_list w; va_list w;

View file

@ -258,126 +258,3 @@ TEST(getrandom, sanityTest) {
} }
} }
} }
TEST(MeasureEntropy, test) {
MeasureEntropy(kMoby, 1000);
EXPECT_EQ(00, lroundl(10 * MeasureEntropy(" ", 12)));
EXPECT_EQ(16, lroundl(10 * MeasureEntropy("abcabcabcabc", 12)));
EXPECT_EQ(36, lroundl(10 * MeasureEntropy("abcdefghijkl", 12)));
EXPECT_EQ(49, lroundl(10 * MeasureEntropy(kMoby, 512)));
}
TEST(MeasureEntropy, testElfExecutable) {
EXPECT_EQ(19, lroundl(10 * MeasureEntropy("\
\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x03\x00\x3e\x00\x01\x00\x00\x00\x18\xd7\x00\x00\x00\x00\x00\x00\
\x40\x00\x00\x00\x00\x00\x00\x00\xc8\xd0\x0c\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x40\x00\x38\x00\x09\x00\x40\x00\x16\x00\x15\x00\
\x06\x00\x00\x00\x04\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\
\x40\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\
\xf8\x01\x00\x00\x00\x00\x00\x00\xf8\x01\x00\x00\x00\x00\x00\x00\
\x08\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\
\x38\x02\x00\x00\x00\x00\x00\x00\x38\x02\x00\x00\x00\x00\x00\x00\
\x38\x02\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\
\x19\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\
\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x90\xbc\x00\x00\x00\x00\x00\x00\x90\xbc\x00\x00\x00\x00\x00\x00\
\x00\x10\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\
\x00\xc0\x00\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\
\x00\xc0\x00\x00\x00\x00\x00\x00\x62\xb2\x09\x00\x00\x00\x00\x00\
\x62\xb2\x09\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\
\x01\x00\x00\x00\x04\x00\x00\x00\x00\x80\x0a\x00\x00\x00\x00\x00\
\x00\x80\x0a\x00\x00\x00\x00\x00\x00\x80\x0a\x00\x00\x00\x00\x00\
\xe4\x09\x02\x00\x00\x00\x00\x00\xe4\x09\x02\x00\x00\x00\x00\x00\
\x00\x10\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\
\xc0\x95\x0c\x00\x00\x00\x00\x00\xc0\xa5\x0c\x00\x00\x00\x00\x00\
\xc0\xa5\x0c\x00\x00\x00\x00\x00\x64\x3a\x00\x00\x00\x00\x00\x00\
\xa8\x42\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\
\x02\x00\x00\x00\x06\x00\x00\x00\xa0\xc2\x0c\x00\x00\x00\x00\x00\
\xa0\xd2\x0c\x00\x00\x00\x00\x00\xa0\xd2\x0c\x00\x00\x00\x00\x00\
\x80\x01\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00\
\x08\x00\x00\x00\x00\x00\x00\x00\x51\xe5\x74\x64\x06\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00",
512)));
}
TEST(MeasureEntropy, testApeExecutable) {
EXPECT_EQ(53, lroundl(10 * MeasureEntropy("\
\x7f\x45\x4c\x46\x02\x01\x01\x09\x00\x00\x00\x00\x00\x00\x00\x00\
\x02\x00\x3e\x00\x01\x00\x00\x00\x0a\x11\x40\x00\x00\x00\x00\x00\
\xe0\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x40\x00\x38\x00\x04\x00\x00\x00\x00\x00\x00\x00\
\xb2\x40\xeb\x00\xeb\x14\x90\x90\xeb\x06\x48\x83\xec\x08\x31\xd2\
\xbd\x00\x00\xeb\x05\xe9\xb0\x10\x00\x00\xfc\x0f\x1f\x87\x3e\xe0\
\xbf\x00\x70\x31\xc9\x8e\xc1\xfa\x8e\xd7\x89\xcc\xfb\x0e\x1f\xe8\
\x00\x00\x5e\x81\xee\x72\x00\xb8\x00\x02\x50\x50\x07\x31\xff\xb9\
\x00\x02\xf3\xa4\x0f\x1f\x87\xd2\xff\xea\x8e\x20\x00\x00\x8e\xd9\
\xb9\x00\x1b\xb8\x50\x00\x8e\xc0\x31\xc0\x31\xff\xf3\xaa\x80\xfa\
\x40\x74\x13\xe8\x15\x00\x07\xb0\x01\x31\xc9\x30\xf6\xbf\x40\x03\
\xe8\x48\x00\x4f\x75\xfa\xea\x20\x25\x00\x00\x53\x52\xb4\x08\xcd\
\x13\x72\x2c\x88\xcf\x80\xe7\x3f\x80\xe1\xc0\xd0\xc1\xd0\xc1\x86\
\xcd\x1e\x06\x1f\x31\xf6\x8e\xc6\xbe\x10\x15\x87\xf7\xa5\xa5\xa5\
\xa5\xa5\xa4\x1f\x93\xab\x91\xab\x92\xab\x58\xaa\x92\x5b\xc3\x5a\
\x80\xf2\x80\x31\xc0\xcd\x13\x72\xf7\xeb\xc1\x50\x51\x86\xcd\xd0\
\xc9\xd0\xc9\x08\xc1\x31\xdb\xb0\x01\xb4\x02\xcd\x13\x59\x58\x72\
\x1d\x8c\xc6\x83\xc6\x20\x8e\xc6\xfe\xc0\x3a\x06\x1c\x15\x76\x0d\
\xb0\x01\xfe\xc6\x3a\x36\x20\x15\x76\x03\x30\xf6\x41\xc3\x50\x31\
\xc0\xcd\x13\x58\xeb\xc5\x89\xfe\xac\x84\xc0\x74\x09\xbb\x07\x00\
\xb4\x0e\xcd\x10\xeb\xf2\xc3\x57\xbf\x78\x24\xe8\xe8\xff\x5f\xe8\
\xe4\xff\xbf\x80\x24\xe8\xde\xff\xf3\x90\xeb\xfc\xb9\x04\x00\xbe\
\x00\x04\xad\x85\xc0\x74\x0b\x51\x56\x97\xbe\x9e\x24\xe8\x05\x00\
\x5e\x59\xe2\xee\xc3\x89\xfa\x85\xd2\x74\x14\x52\x56\x31\xc9\xb1\
\x03\x01\xca\xac\x5e\x0c\x80\xee\x5a\xac\xee\x42\x49\x79\xfa\xc3\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x55\xaa",
512)));
}
TEST(MeasureEntropy, testDevUrandom) {
EXPECT_EQ(76, lroundl(10 * MeasureEntropy("\
\x67\xa6\x8f\x6f\x6f\x01\xa4\x60\xa5\x5a\x6a\xfa\x06\xfd\xbb\xbe\
\xe4\x73\x2f\xc4\x20\x25\xd9\xb2\x78\x7d\x9f\xaf\x5d\x03\x49\x01\
\x90\x94\x8a\xc0\x33\x78\xe0\x65\xd8\x9c\x19\x96\x25\x90\xc8\x6e\
\xf2\x65\xac\x72\xd9\x8e\x58\x05\x26\x22\xa3\x58\x41\x40\xee\x3c\
\x3a\xb0\x08\x7c\x70\x0e\x23\xdc\x52\x10\x21\x5c\xb7\x3d\x3a\xce\
\x7c\xd7\x2a\x8c\x35\x0c\x21\x2b\x03\x75\xbe\x0c\x49\x5b\xdb\x7a\
\x7e\xeb\x27\x03\x56\xca\x9f\xf8\x00\xb4\x4d\x5b\xd6\xde\x41\xd6\
\x86\x7b\x3c\x13\xd4\x2d\xd4\xe9\x79\x05\x48\xcc\xa5\x17\xf8\xb6\
\x74\xdf\x39\x70\x32\x64\x70\x10\xfb\x53\x06\x87\xef\xff\x9f\x4c\
\x07\xee\x09\x54\xb8\xda\x1a\x49\x9b\x12\x3a\xf9\xc3\x55\xbc\xa5\
\xad\x6c\x3d\x1f\x39\x84\xc6\xac\x45\x14\x4f\xa9\xfc\xd6\xfb\xce\
\x41\xf8\x78\x85\xe5\x72\x9c\x0c\xd3\x81\x9b\xa4\x72\xc9\xd5\xc8\
\xc2\x3c\xcc\x36\x58\xf6\x23\x2a\x2e\x9c\x38\xea\x73\x17\xf0\x72\
\x2d\x57\xf8\xc5\x62\x84\xb7\xce\x24\x7b\x46\x65\xc7\xf3\x78\x88\
\x77\x36\x93\x25\x5d\x78\xc9\xfb\x24\xbb\xec\x2f\x77\x4f\x82\xd8\
\x63\x23\xd1\x39\x54\x78\x14\x7d\x24\xc8\x1a\xed\x32\x2d\x7b\xdc\
\xf4\x92\xb1\xaf\x0d\x9b\xba\xb6\x72\xfb\xb2\x7f\x8f\xd5\x4c\x5e\
\x05\xa7\x05\x15\xc5\x51\xd0\x86\x0a\xce\x04\x84\x1e\xba\x44\xf3\
\xbc\x09\xa9\x4e\xc1\xc7\xbd\x7e\x45\x38\x04\xa3\x6c\xfa\x46\x57\
\x40\x93\xbf\xdd\x12\x05\x6c\xb0\xee\x08\x40\x74\xc9\xda\xe7\x30\
\xfa\x1f\x12\xc8\x31\x33\x53\xe4\x65\x2a\xe8\xbf\x2b\x3c\xd6\xcc\
\xec\x8f\x9a\x6f\xe1\xe0\xe6\x81\x0a\xf5\x46\x07\xeb\xcd\xba\xcb\
\xa1\xe5\x4a\x42\xd6\x20\xce\xb6\x16\xcf\x73\x30\x25\x17\xe3\x00\
\x2b\x58\x93\x86\x74\x57\x48\x8b\x2a\x35\x88\xc7\x84\x18\x53\x23\
\xba\xc3\x06\x0a\xd7\x09\xf2\xcb\xe1\xb1\x39\x07\xaf\x2d\xb2\xbc\
\x7d\x71\x91\x6f\x71\x53\x82\xed\x51\x96\xbf\x90\xb4\x4a\x9a\x20\
\x21\x8a\x72\xa3\xbc\xfc\xb9\xcd\x47\x5e\x38\x9c\xd2\xf9\xae\x7f\
\xb2\x1a\x2a\x81\x68\x31\x53\xb2\x11\xfa\x80\x71\x31\xdd\xde\x56\
\x9c\x5f\x3f\x50\xb5\x5f\x99\x5d\x36\x34\x23\x13\xa9\xf0\x04\x3d\
\xa0\xee\x1c\xe5\xe3\x8d\x60\x76\x62\x5a\xd2\xa3\xa2\x51\xea\x75\
\xab\x1f\x2f\xc4\x08\x35\x5d\xf3\x28\x5d\x59\x67\x88\xf0\x61\x6c\
\x8b\x5f\xaf\x90\xa9\x90\xfe\x36\x29\xcc\x02\xf7\x2f\xa7\x19\x0e",
512)));
}
BENCH(getrandom, bench) {
EZBENCH2("MeasureEntropy", donothing, MeasureEntropy(kMoby, 512));
}

View file

@ -0,0 +1,146 @@
/*-*- 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/math.h"
#include "libc/rand/rand.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/hyperion.h"
#include "libc/testlib/testlib.h"
TEST(MeasureEntropy, test) {
MeasureEntropy(kMoby, 1000);
EXPECT_EQ(00, lroundl(10 * MeasureEntropy(" ", 12)));
EXPECT_EQ(16, lroundl(10 * MeasureEntropy("abcabcabcabc", 12)));
EXPECT_EQ(36, lroundl(10 * MeasureEntropy("abcdefghijkl", 12)));
EXPECT_EQ(49, lroundl(10 * MeasureEntropy(kMoby, 512)));
}
TEST(MeasureEntropy, testElfExecutable) {
EXPECT_EQ(19, lroundl(10 * MeasureEntropy("\
\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x03\x00\x3e\x00\x01\x00\x00\x00\x18\xd7\x00\x00\x00\x00\x00\x00\
\x40\x00\x00\x00\x00\x00\x00\x00\xc8\xd0\x0c\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x40\x00\x38\x00\x09\x00\x40\x00\x16\x00\x15\x00\
\x06\x00\x00\x00\x04\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\
\x40\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\
\xf8\x01\x00\x00\x00\x00\x00\x00\xf8\x01\x00\x00\x00\x00\x00\x00\
\x08\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\
\x38\x02\x00\x00\x00\x00\x00\x00\x38\x02\x00\x00\x00\x00\x00\x00\
\x38\x02\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\
\x19\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\
\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x90\xbc\x00\x00\x00\x00\x00\x00\x90\xbc\x00\x00\x00\x00\x00\x00\
\x00\x10\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\
\x00\xc0\x00\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\
\x00\xc0\x00\x00\x00\x00\x00\x00\x62\xb2\x09\x00\x00\x00\x00\x00\
\x62\xb2\x09\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\
\x01\x00\x00\x00\x04\x00\x00\x00\x00\x80\x0a\x00\x00\x00\x00\x00\
\x00\x80\x0a\x00\x00\x00\x00\x00\x00\x80\x0a\x00\x00\x00\x00\x00\
\xe4\x09\x02\x00\x00\x00\x00\x00\xe4\x09\x02\x00\x00\x00\x00\x00\
\x00\x10\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\
\xc0\x95\x0c\x00\x00\x00\x00\x00\xc0\xa5\x0c\x00\x00\x00\x00\x00\
\xc0\xa5\x0c\x00\x00\x00\x00\x00\x64\x3a\x00\x00\x00\x00\x00\x00\
\xa8\x42\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\
\x02\x00\x00\x00\x06\x00\x00\x00\xa0\xc2\x0c\x00\x00\x00\x00\x00\
\xa0\xd2\x0c\x00\x00\x00\x00\x00\xa0\xd2\x0c\x00\x00\x00\x00\x00\
\x80\x01\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00\
\x08\x00\x00\x00\x00\x00\x00\x00\x51\xe5\x74\x64\x06\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00",
512)));
}
TEST(MeasureEntropy, testApeExecutable) {
EXPECT_EQ(53, lroundl(10 * MeasureEntropy("\
\x7f\x45\x4c\x46\x02\x01\x01\x09\x00\x00\x00\x00\x00\x00\x00\x00\
\x02\x00\x3e\x00\x01\x00\x00\x00\x0a\x11\x40\x00\x00\x00\x00\x00\
\xe0\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x40\x00\x38\x00\x04\x00\x00\x00\x00\x00\x00\x00\
\xb2\x40\xeb\x00\xeb\x14\x90\x90\xeb\x06\x48\x83\xec\x08\x31\xd2\
\xbd\x00\x00\xeb\x05\xe9\xb0\x10\x00\x00\xfc\x0f\x1f\x87\x3e\xe0\
\xbf\x00\x70\x31\xc9\x8e\xc1\xfa\x8e\xd7\x89\xcc\xfb\x0e\x1f\xe8\
\x00\x00\x5e\x81\xee\x72\x00\xb8\x00\x02\x50\x50\x07\x31\xff\xb9\
\x00\x02\xf3\xa4\x0f\x1f\x87\xd2\xff\xea\x8e\x20\x00\x00\x8e\xd9\
\xb9\x00\x1b\xb8\x50\x00\x8e\xc0\x31\xc0\x31\xff\xf3\xaa\x80\xfa\
\x40\x74\x13\xe8\x15\x00\x07\xb0\x01\x31\xc9\x30\xf6\xbf\x40\x03\
\xe8\x48\x00\x4f\x75\xfa\xea\x20\x25\x00\x00\x53\x52\xb4\x08\xcd\
\x13\x72\x2c\x88\xcf\x80\xe7\x3f\x80\xe1\xc0\xd0\xc1\xd0\xc1\x86\
\xcd\x1e\x06\x1f\x31\xf6\x8e\xc6\xbe\x10\x15\x87\xf7\xa5\xa5\xa5\
\xa5\xa5\xa4\x1f\x93\xab\x91\xab\x92\xab\x58\xaa\x92\x5b\xc3\x5a\
\x80\xf2\x80\x31\xc0\xcd\x13\x72\xf7\xeb\xc1\x50\x51\x86\xcd\xd0\
\xc9\xd0\xc9\x08\xc1\x31\xdb\xb0\x01\xb4\x02\xcd\x13\x59\x58\x72\
\x1d\x8c\xc6\x83\xc6\x20\x8e\xc6\xfe\xc0\x3a\x06\x1c\x15\x76\x0d\
\xb0\x01\xfe\xc6\x3a\x36\x20\x15\x76\x03\x30\xf6\x41\xc3\x50\x31\
\xc0\xcd\x13\x58\xeb\xc5\x89\xfe\xac\x84\xc0\x74\x09\xbb\x07\x00\
\xb4\x0e\xcd\x10\xeb\xf2\xc3\x57\xbf\x78\x24\xe8\xe8\xff\x5f\xe8\
\xe4\xff\xbf\x80\x24\xe8\xde\xff\xf3\x90\xeb\xfc\xb9\x04\x00\xbe\
\x00\x04\xad\x85\xc0\x74\x0b\x51\x56\x97\xbe\x9e\x24\xe8\x05\x00\
\x5e\x59\xe2\xee\xc3\x89\xfa\x85\xd2\x74\x14\x52\x56\x31\xc9\xb1\
\x03\x01\xca\xac\x5e\x0c\x80\xee\x5a\xac\xee\x42\x49\x79\xfa\xc3\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x55\xaa",
512)));
}
TEST(MeasureEntropy, testDevUrandom) {
EXPECT_EQ(76, lroundl(10 * MeasureEntropy("\
\x67\xa6\x8f\x6f\x6f\x01\xa4\x60\xa5\x5a\x6a\xfa\x06\xfd\xbb\xbe\
\xe4\x73\x2f\xc4\x20\x25\xd9\xb2\x78\x7d\x9f\xaf\x5d\x03\x49\x01\
\x90\x94\x8a\xc0\x33\x78\xe0\x65\xd8\x9c\x19\x96\x25\x90\xc8\x6e\
\xf2\x65\xac\x72\xd9\x8e\x58\x05\x26\x22\xa3\x58\x41\x40\xee\x3c\
\x3a\xb0\x08\x7c\x70\x0e\x23\xdc\x52\x10\x21\x5c\xb7\x3d\x3a\xce\
\x7c\xd7\x2a\x8c\x35\x0c\x21\x2b\x03\x75\xbe\x0c\x49\x5b\xdb\x7a\
\x7e\xeb\x27\x03\x56\xca\x9f\xf8\x00\xb4\x4d\x5b\xd6\xde\x41\xd6\
\x86\x7b\x3c\x13\xd4\x2d\xd4\xe9\x79\x05\x48\xcc\xa5\x17\xf8\xb6\
\x74\xdf\x39\x70\x32\x64\x70\x10\xfb\x53\x06\x87\xef\xff\x9f\x4c\
\x07\xee\x09\x54\xb8\xda\x1a\x49\x9b\x12\x3a\xf9\xc3\x55\xbc\xa5\
\xad\x6c\x3d\x1f\x39\x84\xc6\xac\x45\x14\x4f\xa9\xfc\xd6\xfb\xce\
\x41\xf8\x78\x85\xe5\x72\x9c\x0c\xd3\x81\x9b\xa4\x72\xc9\xd5\xc8\
\xc2\x3c\xcc\x36\x58\xf6\x23\x2a\x2e\x9c\x38\xea\x73\x17\xf0\x72\
\x2d\x57\xf8\xc5\x62\x84\xb7\xce\x24\x7b\x46\x65\xc7\xf3\x78\x88\
\x77\x36\x93\x25\x5d\x78\xc9\xfb\x24\xbb\xec\x2f\x77\x4f\x82\xd8\
\x63\x23\xd1\x39\x54\x78\x14\x7d\x24\xc8\x1a\xed\x32\x2d\x7b\xdc\
\xf4\x92\xb1\xaf\x0d\x9b\xba\xb6\x72\xfb\xb2\x7f\x8f\xd5\x4c\x5e\
\x05\xa7\x05\x15\xc5\x51\xd0\x86\x0a\xce\x04\x84\x1e\xba\x44\xf3\
\xbc\x09\xa9\x4e\xc1\xc7\xbd\x7e\x45\x38\x04\xa3\x6c\xfa\x46\x57\
\x40\x93\xbf\xdd\x12\x05\x6c\xb0\xee\x08\x40\x74\xc9\xda\xe7\x30\
\xfa\x1f\x12\xc8\x31\x33\x53\xe4\x65\x2a\xe8\xbf\x2b\x3c\xd6\xcc\
\xec\x8f\x9a\x6f\xe1\xe0\xe6\x81\x0a\xf5\x46\x07\xeb\xcd\xba\xcb\
\xa1\xe5\x4a\x42\xd6\x20\xce\xb6\x16\xcf\x73\x30\x25\x17\xe3\x00\
\x2b\x58\x93\x86\x74\x57\x48\x8b\x2a\x35\x88\xc7\x84\x18\x53\x23\
\xba\xc3\x06\x0a\xd7\x09\xf2\xcb\xe1\xb1\x39\x07\xaf\x2d\xb2\xbc\
\x7d\x71\x91\x6f\x71\x53\x82\xed\x51\x96\xbf\x90\xb4\x4a\x9a\x20\
\x21\x8a\x72\xa3\xbc\xfc\xb9\xcd\x47\x5e\x38\x9c\xd2\xf9\xae\x7f\
\xb2\x1a\x2a\x81\x68\x31\x53\xb2\x11\xfa\x80\x71\x31\xdd\xde\x56\
\x9c\x5f\x3f\x50\xb5\x5f\x99\x5d\x36\x34\x23\x13\xa9\xf0\x04\x3d\
\xa0\xee\x1c\xe5\xe3\x8d\x60\x76\x62\x5a\xd2\xa3\xa2\x51\xea\x75\
\xab\x1f\x2f\xc4\x08\x35\x5d\xf3\x28\x5d\x59\x67\x88\xf0\x61\x6c\
\x8b\x5f\xaf\x90\xa9\x90\xfe\x36\x29\xcc\x02\xf7\x2f\xa7\x19\x0e",
512)));
}
BENCH(getrandom, bench) {
EZBENCH2("MeasureEntropy", donothing, MeasureEntropy(kMoby, 512));
}

View file

@ -22,14 +22,17 @@
TEST(vappendf, test) { TEST(vappendf, test) {
char *b = 0; char *b = 0;
appendf(&b, "hello "); ASSERT_NE(-1, appendf(&b, "hello "));
EXPECT_EQ(6, appendz(b).i); EXPECT_EQ(6, appendz(b).i);
EXPECT_EQ(0, b[appendz(b).i]);
EXPECT_EQ(6, strlen(b)); // guarantees nul terminator EXPECT_EQ(6, strlen(b)); // guarantees nul terminator
appendf(&b, " world\n"); ASSERT_NE(-1, appendf(&b, " world\n"));
EXPECT_EQ(13, appendz(b).i); EXPECT_EQ(13, appendz(b).i);
EXPECT_EQ(0, b[appendz(b).i]);
EXPECT_EQ(13, strlen(b)); EXPECT_EQ(13, strlen(b));
appendd(&b, "\0", 1); // supports binary ASSERT_NE(-1, appendd(&b, "\0", 1)); // supports binary
EXPECT_EQ(14, appendz(b).i); EXPECT_EQ(14, appendz(b).i);
EXPECT_EQ(0, b[appendz(b).i]);
EXPECT_EQ(13, strlen(b)); EXPECT_EQ(13, strlen(b));
EXPECT_EQ(0, b[13]); EXPECT_EQ(0, b[13]);
EXPECT_EQ(0, b[14]); EXPECT_EQ(0, b[14]);
@ -37,12 +40,17 @@ TEST(vappendf, test) {
free(b); free(b);
} }
TEST(vappends, test) { TEST(appends, test) {
char *b = 0; char *b = 0;
appends(&b, "hello "); ASSERT_NE(-1, appends(&b, ""));
EXPECT_NE(0, b);
EXPECT_EQ(0, appendz(b).i);
EXPECT_EQ(0, b[appendz(b).i]);
ASSERT_NE(-1, appends(&b, "hello "));
EXPECT_EQ(6, appendz(b).i); EXPECT_EQ(6, appendz(b).i);
EXPECT_EQ(0, b[appendz(b).i]);
EXPECT_EQ(6, strlen(b)); // guarantees nul terminator EXPECT_EQ(6, strlen(b)); // guarantees nul terminator
appends(&b, " world\n"); ASSERT_NE(-1, appends(&b, " world\n"));
EXPECT_EQ(13, appendz(b).i); EXPECT_EQ(13, appendz(b).i);
EXPECT_EQ(13, strlen(b)); EXPECT_EQ(13, strlen(b));
EXPECT_EQ(0, b[13]); EXPECT_EQ(0, b[13]);
@ -50,6 +58,69 @@ TEST(vappends, test) {
free(b); free(b);
} }
TEST(appendd, test) {
char *b = 0;
ASSERT_NE(-1, appendd(&b, 0, 0));
EXPECT_NE(0, b);
EXPECT_EQ(0, appendz(b).i);
EXPECT_EQ(0, b[appendz(b).i]);
ASSERT_NE(-1, appendd(&b, "hello ", 6));
EXPECT_EQ(6, appendz(b).i);
EXPECT_EQ(0, b[appendz(b).i]);
EXPECT_EQ(6, strlen(b)); // guarantees nul terminator
ASSERT_NE(-1, appendd(&b, " world\n", 7));
EXPECT_EQ(13, appendz(b).i);
EXPECT_EQ(13, strlen(b));
EXPECT_EQ(0, b[13]);
EXPECT_STREQ("hello world\n", b);
free(b);
}
TEST(appendw, test) {
char *b = 0;
ASSERT_NE(-1, appendw(&b, 0));
EXPECT_EQ(1, appendz(b).i);
EXPECT_EQ(0, b[0]);
EXPECT_EQ(0, b[1]);
ASSERT_NE(-1, appendw(&b, 'h'));
EXPECT_EQ(2, appendz(b).i);
EXPECT_EQ(0, b[0]);
EXPECT_EQ('h', b[1]);
EXPECT_EQ(0, b[2]);
ASSERT_NE(-1, appendw(&b, 'e' | 'l' << 8 | 'l' << 16 | 'o' << 24 |
(uint64_t)'!' << 32));
EXPECT_EQ(7, appendz(b).i);
EXPECT_EQ(0, b[0]);
EXPECT_EQ('h', b[1]);
EXPECT_EQ('e', b[2]);
EXPECT_EQ('l', b[3]);
EXPECT_EQ('l', b[4]);
EXPECT_EQ('o', b[5]);
EXPECT_EQ('!', b[6]);
EXPECT_EQ(0, b[7]);
free(b);
}
TEST(appendr, test) {
char *b = 0;
ASSERT_NE(-1, appends(&b, "hello"));
EXPECT_EQ(5, appendz(b).i);
ASSERT_NE(-1, appendr(&b, 1));
EXPECT_EQ(0, strcmp(b, "h"));
EXPECT_EQ(1, appendz(b).i);
ASSERT_NE(-1, appendr(&b, 0));
EXPECT_EQ(0, appendz(b).i);
EXPECT_EQ(0, strcmp(b, ""));
ASSERT_NE(-1, appendr(&b, 5));
EXPECT_EQ(0, b[0]);
EXPECT_EQ(0, b[1]);
EXPECT_EQ(0, b[2]);
EXPECT_EQ(0, b[3]);
EXPECT_EQ(0, b[4]);
EXPECT_EQ(0, b[5]);
free(b);
}
BENCH(vappendf, bench) { BENCH(vappendf, bench) {
const char t[] = {0}; const char t[] = {0};
char *b = 0; char *b = 0;
@ -57,6 +128,8 @@ BENCH(vappendf, bench) {
free(b), b = 0; free(b), b = 0;
EZBENCH2("appends", donothing, appends(&b, "1")); EZBENCH2("appends", donothing, appends(&b, "1"));
free(b), b = 0; free(b), b = 0;
EZBENCH2("appendw", donothing, appendw(&b, 'B'));
free(b), b = 0;
EZBENCH2("appendd", donothing, appendd(&b, t, 1)); EZBENCH2("appendd", donothing, appendd(&b, t, 1));
free(b); free(b), b = 0;
} }

View file

@ -16,6 +16,8 @@
#include "third_party/lua/lua.h" #include "third_party/lua/lua.h"
#include "third_party/lua/lualib.h" #include "third_party/lua/lualib.h"
const char *g_lua_path_default = LUA_PATH_DEFAULT;
/* clang-format off */ /* clang-format off */
/* /*
@ -728,12 +730,17 @@ static void createclibstable (lua_State *L) {
} }
static const char *GetLuaPathDefault(void) {
return g_lua_path_default;
}
LUAMOD_API int luaopen_package (lua_State *L) { LUAMOD_API int luaopen_package (lua_State *L) {
createclibstable(L); createclibstable(L);
luaL_newlib(L, pk_funcs); /* create 'package' table */ luaL_newlib(L, pk_funcs); /* create 'package' table */
createsearcherstable(L); createsearcherstable(L);
/* set paths */ /* set paths */
setpath(L, "path", LUA_PATH_VAR, LUA_PATH_DEFAULT); setpath(L, "path", LUA_PATH_VAR, g_lua_path_default);
setpath(L, "cpath", LUA_CPATH_VAR, LUA_CPATH_DEFAULT); setpath(L, "cpath", LUA_CPATH_VAR, LUA_CPATH_DEFAULT);
/* store config information */ /* store config information */
lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"

44
third_party/lua/lua.h vendored
View file

@ -1,15 +1,8 @@
/* #ifndef COSMOPOLITAN_THIRD_PARTY_LUA_LUA_H_
** $Id: lua.h $ #define COSMOPOLITAN_THIRD_PARTY_LUA_LUA_H_
** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file
*/
#ifndef lua_h
#define lua_h
#include "third_party/lua/luaconf.h" #include "third_party/lua/luaconf.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/* clang-format off */ /* clang-format off */
#define LUA_VERSION_MAJOR "5" #define LUA_VERSION_MAJOR "5"
@ -489,29 +482,8 @@ struct lua_Debug {
/* }====================================================================== */ /* }====================================================================== */
extern const char *g_lua_path_default;
/****************************************************************************** COSMOPOLITAN_C_END_
* Copyright (C) 1994-2021 Lua.org, PUC-Rio. #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
* #endif /* COSMOPOLITAN_THIRD_PARTY_LUA_LUA_H_ */
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/
#endif

View file

@ -60,6 +60,11 @@ o/$(MODE)/third_party/lua/lauxlib.o: \
OVERRIDE_CFLAGS += \ OVERRIDE_CFLAGS += \
-DSTACK_FRAME_UNLIMITED -DSTACK_FRAME_UNLIMITED
$(THIRD_PARTY_LUA_OBJS): \
OVERRIDE_CFLAGS += \
-ffunction-sections \
-fdata-sections
.PHONY: o/$(MODE)/third_party/lua .PHONY: o/$(MODE)/third_party/lua
o/$(MODE)/third_party/lua: \ o/$(MODE)/third_party/lua: \
$(THIRD_PARTY_LUA_BINS) \ $(THIRD_PARTY_LUA_BINS) \

View file

@ -1,17 +1,13 @@
/*
** $Id: luaconf.h $
** Configuration file for Lua
** See Copyright Notice in lua.h
*/
#ifndef luaconf_h #ifndef luaconf_h
#define luaconf_h #define luaconf_h
#include "libc/assert.h"
#define LUA_USE_POSIX #include "libc/dce.h"
#include "libc/fmt/fmt.h" #include "libc/fmt/fmt.h"
#include "libc/limits.h" #include "libc/limits.h"
#include "third_party/gdtoa/gdtoa.h" #include "third_party/gdtoa/gdtoa.h"
#define LUA_USE_POSIX
/* clang-format off */ /* clang-format off */
/* /*
@ -193,63 +189,20 @@
*/ */
#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR #define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#if defined(_WIN32) /* { */
/*
** In Windows, any exclamation mark ('!') in the path is replaced by the
** path of the directory of the executable file of the current process.
*/
#define LUA_LDIR "!\\lua\\"
#define LUA_CDIR "!\\"
#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\"
#if !defined(LUA_PATH_DEFAULT)
#define LUA_PATH_DEFAULT \
LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \
LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \
".\\?.lua;" ".\\?\\init.lua"
#endif
#if !defined(LUA_CPATH_DEFAULT)
#define LUA_CPATH_DEFAULT \
LUA_CDIR"?.dll;" \
LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \
LUA_CDIR"loadall.dll;" ".\\?.dll"
#endif
#else /* }{ */
#define LUA_ROOT "zip:" #define LUA_ROOT "zip:"
#define LUA_LDIR LUA_ROOT ".lua/" #define LUA_LDIR LUA_ROOT ".lua/"
#define LUA_CDIR LUA_ROOT ".lua/" #define LUA_CDIR LUA_ROOT ".lua/"
#if !defined(LUA_PATH_DEFAULT) #define LUA_PATH_DEFAULT LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" "./?.lua;" "./?/init.lua"
#define LUA_PATH_DEFAULT \ #define LUA_CPATH_DEFAULT LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"
LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua"
#endif
#if !defined(LUA_CPATH_DEFAULT)
#define LUA_CPATH_DEFAULT \
LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"
#endif
#endif /* } */
/* /*
@@ LUA_DIRSEP is the directory separator (for submodules). @@ LUA_DIRSEP is the directory separator (for submodules).
** CHANGE it if your machine does not use "/" as the directory separator ** CHANGE it if your machine does not use "/" as the directory separator
** and is not Windows. (On Windows Lua automatically uses "\".) ** and is not Windows. (On Windows Lua automatically uses "\".)
*/ */
#if !defined(LUA_DIRSEP)
#if defined(_WIN32)
#define LUA_DIRSEP "\\"
#else
#define LUA_DIRSEP "/" #define LUA_DIRSEP "/"
#endif
#endif
/* }================================================================== */ /* }================================================================== */
@ -269,20 +222,8 @@
** the libraries, you may want to use the following definition (define ** the libraries, you may want to use the following definition (define
** LUA_BUILD_AS_DLL to get it). ** LUA_BUILD_AS_DLL to get it).
*/ */
#if defined(LUA_BUILD_AS_DLL) /* { */
#if defined(LUA_CORE) || defined(LUA_LIB) /* { */
#define LUA_API __declspec(dllexport)
#else /* }{ */
#define LUA_API __declspec(dllimport)
#endif /* } */
#else /* }{ */
#define LUA_API extern #define LUA_API extern
#endif /* } */
/* /*
** More often than not the libs go together with the core. ** More often than not the libs go together with the core.
@ -305,12 +246,7 @@
** give a warning about it. To avoid these warnings, change to the ** give a warning about it. To avoid these warnings, change to the
** default definition. ** default definition.
*/ */
#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
defined(__ELF__) /* { */
#define LUAI_FUNC /* __attribute__((visibility("internal"))) */ extern
#else /* }{ */
#define LUAI_FUNC extern #define LUAI_FUNC extern
#endif /* } */
#define LUAI_DDEC(dec) LUAI_FUNC dec #define LUAI_DDEC(dec) LUAI_FUNC dec
#define LUAI_DDEF /* empty */ #define LUAI_DDEF /* empty */
@ -710,8 +646,7 @@
@@ LUA_USE_APICHECK turns on several consistency checks on the C API. @@ LUA_USE_APICHECK turns on several consistency checks on the C API.
** Define it as a help when debugging C code. ** Define it as a help when debugging C code.
*/ */
#if defined(LUA_USE_APICHECK) #if IsModeDbg()
#include <assert.h>
#define luai_apicheck(l,e) assert(e) #define luai_apicheck(l,e) assert(e)
#endif #endif

View file

@ -2,6 +2,7 @@
#define MBEDTLS_CONFIG_H_ #define MBEDTLS_CONFIG_H_
#include "libc/dce.h" #include "libc/dce.h"
/* /\* uncomment for testing old cpu code paths *\/ */
/* #include "libc/nexgen32e/x86feature.h" */ /* #include "libc/nexgen32e/x86feature.h" */
/* #undef X86_HAVE */ /* #undef X86_HAVE */
/* #define X86_HAVE(x) 0 */ /* #define X86_HAVE(x) 0 */

View file

@ -35,21 +35,22 @@ mbedtls_p384_isz( uint64_t p[6] )
return( !p[0] & !p[1] & !p[2] & !p[3] & !p[4] & !p[5] ); return( !p[0] & !p[1] & !p[2] & !p[3] & !p[4] & !p[5] );
} }
bool mbedtls_p384_gte( uint64_t p[7] ) static bool
mbedtls_p384_gte( uint64_t p[7] )
{ {
return( (((int64_t)p[6] > 0) | return( (((int64_t)p[6] > 0) |
(!p[6] & (!p[6] &
(p[5] > 0xffffffffffffffff | ((p[5] > 0xffffffffffffffff) |
(p[5] == 0xffffffffffffffff & ((p[5] == 0xffffffffffffffff) &
(p[4] > 0xffffffffffffffff | ((p[4] > 0xffffffffffffffff) |
(p[4] == 0xffffffffffffffff & ((p[4] == 0xffffffffffffffff) &
(p[3] > 0xffffffffffffffff | ((p[3] > 0xffffffffffffffff) |
(p[3] == 0xffffffffffffffff & ((p[3] == 0xffffffffffffffff) &
(p[2] > 0xfffffffffffffffe | ((p[2] > 0xfffffffffffffffe) |
(p[2] == 0xfffffffffffffffe & ((p[2] == 0xfffffffffffffffe) &
(p[1] > 0xffffffff00000000 | ((p[1] > 0xffffffff00000000) |
(p[1] == 0xffffffff00000000 & ((p[1] == 0xffffffff00000000) &
(p[0] > 0x00000000ffffffff | ((p[0] > 0x00000000ffffffff) |
(p[0] == 0x00000000ffffffff)))))))))))))) ); (p[0] == 0x00000000ffffffff)))))))))))))) );
} }
@ -128,7 +129,8 @@ mbedtls_p384_gro( uint64_t p[7] )
#endif #endif
} }
void mbedtls_p384_rum( uint64_t p[7] ) static inline void
mbedtls_p384_rum( uint64_t p[7] )
{ {
while( mbedtls_p384_gte( p ) ) while( mbedtls_p384_gte( p ) )
mbedtls_p384_red( p ); mbedtls_p384_red( p );
@ -142,9 +144,7 @@ void mbedtls_p384_mod( uint64_t X[12] )
mbedtls_p384_gro(X); mbedtls_p384_gro(X);
} while( (int64_t)X[6] < 0 ); } while( (int64_t)X[6] < 0 );
} else { } else {
while( mbedtls_p384_gte(X) ){ mbedtls_p384_rum(X);
mbedtls_p384_red(X);
}
} }
} }

View file

@ -261,7 +261,6 @@ int mbedtls_p384_normalize_jac( const mbedtls_ecp_group *,
int mbedtls_p384_normalize_jac_many( const mbedtls_ecp_group *, int mbedtls_p384_normalize_jac_many( const mbedtls_ecp_group *,
mbedtls_ecp_point *[], size_t ); mbedtls_ecp_point *[], size_t );
void mbedtls_p384_rum( uint64_t p[7] );
void mbedtls_p384_mod( uint64_t X[12] ); void mbedtls_p384_mod( uint64_t X[12] );
#endif /* COSMOPOLITAN_THIRD_PARTY_MBEDTLS_ECP_INTERNAL_H_ */ #endif /* COSMOPOLITAN_THIRD_PARTY_MBEDTLS_ECP_INTERNAL_H_ */

View file

@ -27,6 +27,8 @@
#include "third_party/mbedtls/math.h" #include "third_party/mbedtls/math.h"
#ifdef MBEDTLS_ECP_C #ifdef MBEDTLS_ECP_C
/*P=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff*/
int ecp_mod_p384_old(mbedtls_mpi *); int ecp_mod_p384_old(mbedtls_mpi *);
int GetEntropy(void *c, unsigned char *p, size_t n) { int GetEntropy(void *c, unsigned char *p, size_t n) {
@ -97,14 +99,6 @@ TEST(secp384r1, needsDownwardCorrection) {
TEST(secp384r1, needsUpwardCorrection) { TEST(secp384r1, needsUpwardCorrection) {
int i; int i;
uint64_t P[6] = {
0x00000000ffffffff, //
0xffffffff00000000, //
0xfffffffffffffffe, //
0xffffffffffffffff, //
0xffffffffffffffff, //
0xffffffffffffffff, //
};
uint64_t X[12] = { uint64_t X[12] = {
0x0000000000000000, // 0x0000000000000000, //
0x0000000000000000, // 0x0000000000000000, //
@ -136,6 +130,35 @@ TEST(secp384r1, needsUpwardCorrection) {
} }
} }
TEST(secp384r1, largestInput_quasiModNeedsTwoDownwardCorrections) {
int i;
uint64_t X[12] = {
// X = (P-1)*(P-1)
0xfffffffc00000004, //
0x0000000400000000, //
0xfffffffe00000002, //
0x0000000200000000, //
0x0000000000000001, //
0x0000000000000000, //
0x00000001fffffffc, //
0xfffffffe00000000, //
0xfffffffffffffffd, //
0xffffffffffffffff, //
0xffffffffffffffff, //
0xffffffffffffffff, //
};
uint64_t W[12] /* W = X mod P */ = {
0x0000000000000001, //
};
mbedtls_p384_mod(X);
if (memcmp(W, X, 12 * 8)) {
for (i = 0; i < 12; ++i) {
printf("0x%016lx vs. 0x%016lx %d\n", W[i], X[i], W[i] == X[i]);
}
ASSERT_TRUE(false);
}
}
BENCH(secp384r1, bench) { BENCH(secp384r1, bench) {
mbedtls_mpi A; mbedtls_mpi A;
mbedtls_mpi_init(&A); mbedtls_mpi_init(&A);

View file

@ -1,3 +1,3 @@
SetStatus(200) SetStatus(200)
SetHeader("Content-Type", GetHeader("Content-Type")) SetHeader("Content-Type", GetHeader("Content-Type") or "text/plain")
Write(GetPayload()) Write(GetPayload())

View file

@ -244,7 +244,8 @@ SECURITY
Subject Alternative Names (SAN) or the Common Name (CN) of subject if Subject Alternative Names (SAN) or the Common Name (CN) of subject if
SAN isn't used. This means you don't need to reveal your whole domain SAN isn't used. This means you don't need to reveal your whole domain
portfolio to each client just to have ssl. You can just use different portfolio to each client just to have ssl. You can just use different
certificates for each domain if you choose to do so. certificates for each domain if you choose to do so. If redbean can't
find an appropriate match, then the first certificate will be chosen.
Your redbean has been secured with algorithms so strong that, until a Your redbean has been secured with algorithms so strong that, until a
few decades ago, it was illegal to share them with with those outside few decades ago, it was illegal to share them with with those outside

View file

@ -151,7 +151,6 @@ o/$(MODE)/tool/net/redbean-demo.com: \
@$(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -qj $@ tool/net/demo/404.html tool/net/favicon.ico tool/net/redbean.png tool/net/demo/redbean-form.lua tool/net/demo/redbean-xhr.lua tool/net/demo/printpayload.lua tool/net/demo/fetch.lua @$(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -qj $@ tool/net/demo/404.html tool/net/favicon.ico tool/net/redbean.png tool/net/demo/redbean-form.lua tool/net/demo/redbean-xhr.lua tool/net/demo/printpayload.lua tool/net/demo/fetch.lua
@echo Uncompressed for HTTP Range requests | $(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -cqj0 $@ tool/net/demo/seekable.txt @echo Uncompressed for HTTP Range requests | $(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -cqj0 $@ tool/net/demo/seekable.txt
@$(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -q $@ tool/net/ tool/net/demo/ tool/net/demo/index.html tool/net/demo/redbean.css tool/net/redbean.c net/http/parsehttpmessage.c net/http/parseurl.c net/http/encodeurl.c test/net/http/parsehttpmessage_test.c test/net/http/parseurl_test.c @$(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -q $@ tool/net/ tool/net/demo/ tool/net/demo/index.html tool/net/demo/redbean.css tool/net/redbean.c net/http/parsehttpmessage.c net/http/parseurl.c net/http/encodeurl.c test/net/http/parsehttpmessage_test.c test/net/http/parseurl_test.c
@printf "<p>Thank you for using <a href=https://justine.lol/redbean/>redbean</a> the tiniest most vertically integrated actually portable web server with superior performance." | $(COMPILE) -AZIP -T$@ o/$(MODE)/host/third_party/infozip/zip.com -z $@
@$(COMPILE) -AMKDIR -T$@ mkdir -p o/$(MODE)/tool/net/virtualbean.justine.lol/ @$(COMPILE) -AMKDIR -T$@ mkdir -p o/$(MODE)/tool/net/virtualbean.justine.lol/
@$(COMPILE) -ACP -T$@ cp tool/net/redbean.png o/$(MODE)/tool/net/virtualbean.justine.lol/redbean.png @$(COMPILE) -ACP -T$@ cp tool/net/redbean.png o/$(MODE)/tool/net/virtualbean.justine.lol/redbean.png
@$(COMPILE) -ACP -T$@ cp tool/net/demo/virtualbean.html o/$(MODE)/tool/net/virtualbean.justine.lol/index.html @$(COMPILE) -ACP -T$@ cp tool/net/demo/virtualbean.html o/$(MODE)/tool/net/virtualbean.justine.lol/index.html

View file

@ -51,6 +51,7 @@
#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/append.internal.h"
#include "libc/stdio/stdio.h" #include "libc/stdio/stdio.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/str/undeflate.h" #include "libc/str/undeflate.h"
@ -91,6 +92,7 @@
#include "third_party/lua/lauxlib.h" #include "third_party/lua/lauxlib.h"
#include "third_party/lua/ltests.h" #include "third_party/lua/ltests.h"
#include "third_party/lua/lua.h" #include "third_party/lua/lua.h"
#include "third_party/lua/luaconf.h"
#include "third_party/lua/lualib.h" #include "third_party/lua/lualib.h"
#include "third_party/mbedtls/asn1.h" #include "third_party/mbedtls/asn1.h"
#include "third_party/mbedtls/asn1write.h" #include "third_party/mbedtls/asn1write.h"
@ -352,6 +354,7 @@ static uint32_t clientaddrsize;
static lua_State *L; static lua_State *L;
static size_t zsize; static size_t zsize;
static char *outbuf;
static char *content; static char *content;
static uint8_t *zmap; static uint8_t *zmap;
static uint8_t *zbase; static uint8_t *zbase;
@ -384,7 +387,6 @@ static ssize_t (*generator)(struct iovec[3]);
static struct Buffer inbuf; static struct Buffer inbuf;
static struct Buffer oldin; static struct Buffer oldin;
static struct Buffer hdrbuf; static struct Buffer hdrbuf;
static struct Buffer outbuf;
static struct timeval timeout; static struct timeval timeout;
static struct Buffer effectivepath; static struct Buffer effectivepath;
@ -526,57 +528,14 @@ static void CollectGarbage(void) {
} }
static void UseOutput(void) { static void UseOutput(void) {
content = FreeLater(outbuf.p); content = FreeLater(outbuf);
contentlength = outbuf.n; contentlength = appendz(outbuf).i;
outbuf.p = 0; outbuf = 0;
outbuf.n = 0;
outbuf.c = 0;
} }
static void DropOutput(void) { static void DropOutput(void) {
FreeLater(outbuf.p); FreeLater(outbuf);
outbuf.p = 0; outbuf = 0;
outbuf.n = 0;
outbuf.c = 0;
}
static void ClearOutput(void) {
outbuf.n = 0;
}
static void Grow(size_t n) {
do {
if (outbuf.c) {
outbuf.c += outbuf.c >> 1;
} else {
outbuf.c = 16 * 1024;
}
} while (n > outbuf.c);
outbuf.p = xrealloc(outbuf.p, outbuf.c);
}
static void AppendData(const char *data, size_t size) {
size_t n;
n = outbuf.n + size;
if (n > outbuf.c) Grow(n);
memcpy(outbuf.p + outbuf.n, data, size);
outbuf.n = n;
}
static void Append(const char *fmt, ...) {
int n;
char *p;
va_list va, vb;
va_start(va, fmt);
va_copy(vb, va);
n = vsnprintf(outbuf.p + outbuf.n, outbuf.c - outbuf.n, fmt, va);
if (n >= outbuf.c - outbuf.n) {
Grow(outbuf.n + n + 1);
vsnprintf(outbuf.p + outbuf.n, outbuf.c - outbuf.n, fmt, vb);
}
va_end(vb);
va_end(va);
outbuf.n += n;
} }
static char *MergePaths(const char *p, size_t n, const char *q, size_t m, static char *MergePaths(const char *p, size_t n, const char *q, size_t m,
@ -641,9 +600,11 @@ static mbedtls_x509_crt *GetTrustedCertificate(mbedtls_x509_name *name) {
return 0; return 0;
} }
static void UseCertificate(mbedtls_ssl_config *c, struct Cert *kp) { static void UseCertificate(mbedtls_ssl_config *c, struct Cert *kp,
VERBOSEF("using %s certificate %`'s", mbedtls_pk_get_name(&kp->cert->pk), const char *role) {
gc(FormatX509Name(&kp->cert->subject))); VERBOSEF("using %s certificate %`'s for HTTPS %s",
mbedtls_pk_get_name(&kp->cert->pk),
gc(FormatX509Name(&kp->cert->subject)), role);
CHECK_EQ(0, mbedtls_ssl_conf_own_cert(c, kp->cert, kp->key)); CHECK_EQ(0, mbedtls_ssl_conf_own_cert(c, kp->cert, kp->key));
} }
@ -947,8 +908,8 @@ static void ProgramTimeout(long ms) {
timeout.tv_sec = ms; /* -(keepalive seconds) */ timeout.tv_sec = ms; /* -(keepalive seconds) */
timeout.tv_usec = 0; timeout.tv_usec = 0;
} else { } else {
if (ms <= 30) { if (ms < 10) {
fprintf(stderr, "error: timeout needs to be 31ms or greater\n"); fprintf(stderr, "error: timeout needs to be 10ms or greater\n");
exit(1); exit(1);
} }
d = ldiv(ms, 1000); d = ldiv(ms, 1000);
@ -1168,57 +1129,57 @@ static void ReportWorkerExit(int pid, int ws) {
} }
} }
static void AppendResourceReport(struct rusage *ru, const char *nl) { static void AppendResourceReport(char **b, struct rusage *ru, const char *nl) {
long utime, stime; long utime, stime;
long double ticks; long double ticks;
if (ru->ru_maxrss) { if (ru->ru_maxrss) {
Append("ballooned to %,ldkb in size%s", ru->ru_maxrss, nl); appendf(b, "ballooned to %,ldkb in size%s", ru->ru_maxrss, nl);
} }
if ((utime = ru->ru_utime.tv_sec * 1000000 + ru->ru_utime.tv_usec) | if ((utime = ru->ru_utime.tv_sec * 1000000 + ru->ru_utime.tv_usec) |
(stime = ru->ru_stime.tv_sec * 1000000 + ru->ru_stime.tv_usec)) { (stime = ru->ru_stime.tv_sec * 1000000 + ru->ru_stime.tv_usec)) {
ticks = ceill((long double)(utime + stime) / (1000000.L / CLK_TCK)); ticks = ceill((long double)(utime + stime) / (1000000.L / CLK_TCK));
Append("needed %,ldµs cpu (%d%% kernel)%s", utime + stime, appendf(b, "needed %,ldµs cpu (%d%% kernel)%s", utime + stime,
(int)((long double)stime / (utime + stime) * 100), nl); (int)((long double)stime / (utime + stime) * 100), nl);
if (ru->ru_idrss) { if (ru->ru_idrss) {
Append("needed %,ldkb memory on average%s", lroundl(ru->ru_idrss / ticks), appendf(b, "needed %,ldkb memory on average%s",
nl); lroundl(ru->ru_idrss / ticks), nl);
} }
if (ru->ru_isrss) { if (ru->ru_isrss) {
Append("needed %,ldkb stack on average%s", lroundl(ru->ru_isrss / ticks), appendf(b, "needed %,ldkb stack on average%s",
nl); lroundl(ru->ru_isrss / ticks), nl);
} }
if (ru->ru_ixrss) { if (ru->ru_ixrss) {
Append("mapped %,ldkb shared on average%s", lroundl(ru->ru_ixrss / ticks), appendf(b, "mapped %,ldkb shared on average%s",
nl); lroundl(ru->ru_ixrss / ticks), nl);
} }
} }
if (ru->ru_minflt || ru->ru_majflt) { if (ru->ru_minflt || ru->ru_majflt) {
Append("caused %,ld page faults (%d%% memcpy)%s", appendf(b, "caused %,ld page faults (%d%% memcpy)%s",
ru->ru_minflt + ru->ru_majflt, ru->ru_minflt + ru->ru_majflt,
(int)((long double)ru->ru_minflt / (ru->ru_minflt + ru->ru_majflt) * (int)((long double)ru->ru_minflt / (ru->ru_minflt + ru->ru_majflt) *
100), 100),
nl); nl);
} }
if (ru->ru_nvcsw + ru->ru_nivcsw > 1) { if (ru->ru_nvcsw + ru->ru_nivcsw > 1) {
Append( appendf(
"%,ld context switches (%d%% consensual)%s", b, "%,ld context switches (%d%% consensual)%s",
ru->ru_nvcsw + ru->ru_nivcsw, ru->ru_nvcsw + ru->ru_nivcsw,
(int)((long double)ru->ru_nvcsw / (ru->ru_nvcsw + ru->ru_nivcsw) * 100), (int)((long double)ru->ru_nvcsw / (ru->ru_nvcsw + ru->ru_nivcsw) * 100),
nl); nl);
} }
if (ru->ru_msgrcv || ru->ru_msgsnd) { if (ru->ru_msgrcv || ru->ru_msgsnd) {
Append("received %,ld message%s and sent %,ld%s", ru->ru_msgrcv, appendf(b, "received %,ld message%s and sent %,ld%s", ru->ru_msgrcv,
ru->ru_msgrcv == 1 ? "" : "s", ru->ru_msgsnd, nl); ru->ru_msgrcv == 1 ? "" : "s", ru->ru_msgsnd, nl);
} }
if (ru->ru_inblock || ru->ru_oublock) { if (ru->ru_inblock || ru->ru_oublock) {
Append("performed %,ld read%s and %,ld write i/o operations%s", appendf(b, "performed %,ld read%s and %,ld write i/o operations%s",
ru->ru_inblock, ru->ru_inblock == 1 ? "" : "s", ru->ru_oublock, nl); ru->ru_inblock, ru->ru_inblock == 1 ? "" : "s", ru->ru_oublock, nl);
} }
if (ru->ru_nsignals) { if (ru->ru_nsignals) {
Append("received %,ld signals%s", ru->ru_nsignals, nl); appendf(b, "received %,ld signals%s", ru->ru_nsignals, nl);
} }
if (ru->ru_nswap) { if (ru->ru_nswap) {
Append("got swapped %,ld times%s", ru->ru_nswap, nl); appendf(b, "got swapped %,ld times%s", ru->ru_nswap, nl);
} }
} }
@ -1251,16 +1212,16 @@ static void AddRusage(struct rusage *x, const struct rusage *y) {
} }
static void ReportWorkerResources(int pid, struct rusage *ru) { static void ReportWorkerResources(int pid, struct rusage *ru) {
const char *s; char *s, *b = 0;
if (logrusage || LOGGABLE(kLogDebug)) { if (logrusage || LOGGABLE(kLogDebug)) {
AppendResourceReport(ru, "\n"); AppendResourceReport(&b, ru, "\n");
if (outbuf.n) { if (b) {
if ((s = IndentLines(outbuf.p, outbuf.n - 1, 0, 1))) { if ((s = IndentLines(b, appendz(b).i - 1, 0, 1))) {
flogf(kLogInfo, __FILE__, __LINE__, NULL, flogf(kLogInfo, __FILE__, __LINE__, NULL,
"resource report for pid %d\n%s", pid, s); "resource report for pid %d\n%s", pid, s);
free(s); free(s);
} }
ClearOutput(); free(b);
} }
} }
} }
@ -1512,68 +1473,101 @@ static void WipeServingKeys(void) {
/* mbedtls_ssl_key_cert_free(conf.key_cert); */ /* mbedtls_ssl_key_cert_free(conf.key_cert); */
} }
static int TlsRouteCertificate(mbedtls_ssl_context *ssl, int i, static bool CertHasCommonName(const mbedtls_x509_crt *cert,
const unsigned char *host, size_t size) { const unsigned char *host, size_t size) {
int rc; const mbedtls_x509_name *name;
if (!(rc = mbedtls_ssl_set_hs_own_cert(ssl, certs.p[i].cert, for (name = &cert->subject; name; name = name->next) {
certs.p[i].key))) { if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid)) {
DEBUGF("TlsRoute(%`'.*s) %s %`'s", size, host, if (SlicesEqualCase(host, size, name->val.p, name->val.len)) {
return true;
}
break;
}
}
return false;
}
static bool CertHasHost(const mbedtls_x509_crt *cert, const unsigned char *host,
size_t size) {
const mbedtls_x509_sequence *cur;
for (cur = &cert->subject_alt_names; cur; cur = cur->next) {
if ((cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) ==
MBEDTLS_X509_SAN_DNS_NAME &&
SlicesEqualCase(host, size, cur->buf.p, cur->buf.len)) {
return true;
}
}
return false;
}
static bool CertHasIp(const mbedtls_x509_crt *cert, uint32_t ip) {
const mbedtls_x509_sequence *cur;
for (cur = &cert->subject_alt_names; cur; cur = cur->next) {
if ((cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) ==
MBEDTLS_X509_SAN_IP_ADDRESS &&
cur->buf.len == 4 && ip == READ32BE(cur->buf.p)) {
return true;
}
}
return false;
}
static bool IsServerCert(mbedtls_pk_type_t type, int i) {
return certs.p[i].cert && certs.p[i].key && !certs.p[i].cert->ca_istrue &&
mbedtls_pk_get_type(certs.p[i].key) == type &&
!mbedtls_x509_crt_check_extended_key_usage(
certs.p[i].cert, MBEDTLS_OID_SERVER_AUTH,
MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH));
}
static bool TlsRouteFind(mbedtls_pk_type_t type, mbedtls_ssl_context *ssl,
const unsigned char *host, size_t size, int64_t ip) {
int i;
for (i = 0; i < certs.n; ++i) {
if (IsServerCert(type, i) &&
(((certs.p[i].cert->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) &&
(ip == -1 ? CertHasHost(certs.p[i].cert, host, size)
: CertHasIp(certs.p[i].cert, ip))) ||
CertHasCommonName(certs.p[i].cert, host, size))) {
CHECK_EQ(
0, mbedtls_ssl_set_hs_own_cert(ssl, certs.p[i].cert, certs.p[i].key));
DEBUGF("TlsRoute(%s, %`'.*s) %s %`'s", mbedtls_pk_type_name(type), size,
host, mbedtls_pk_get_name(&certs.p[i].cert->pk),
gc(FormatX509Name(&certs.p[i].cert->subject)));
return true;
}
}
return false;
}
static bool TlsRouteFirst(mbedtls_pk_type_t type, mbedtls_ssl_context *ssl) {
int i;
for (i = 0; i < certs.n; ++i) {
if (IsServerCert(type, i)) {
CHECK_EQ(
0, mbedtls_ssl_set_hs_own_cert(ssl, certs.p[i].cert, certs.p[i].key));
DEBUGF("TlsRoute(%s) %s %`'s", mbedtls_pk_type_name(type),
mbedtls_pk_get_name(&certs.p[i].cert->pk), mbedtls_pk_get_name(&certs.p[i].cert->pk),
gc(FormatX509Name(&certs.p[i].cert->subject))); gc(FormatX509Name(&certs.p[i].cert->subject)));
return 0; return true;
} else {
return -1;
} }
}
return false;
} }
static int TlsRoute(void *ctx, mbedtls_ssl_context *ssl, static int TlsRoute(void *ctx, mbedtls_ssl_context *ssl,
const unsigned char *host, size_t size) { const unsigned char *host, size_t size) {
int rc;
size_t i;
int64_t ip; int64_t ip;
int santype; bool ok1, ok2;
const mbedtls_x509_name *name;
const mbedtls_x509_sequence *cur;
ip = ParseIp((const char *)host, size); ip = ParseIp((const char *)host, size);
for (rc = -1, i = 0; i < certs.n; ++i) { ok1 = TlsRouteFind(MBEDTLS_PK_ECKEY, ssl, host, size, ip);
if (!certs.p[i].key || !certs.p[i].cert || certs.p[i].cert->ca_istrue || ok2 = TlsRouteFind(MBEDTLS_PK_RSA, ssl, host, size, ip);
mbedtls_x509_crt_check_extended_key_usage( if (!ok1 && !ok2) {
certs.p[i].cert, MBEDTLS_OID_SERVER_AUTH, VERBOSEF("TlsRoute(%`'.*s) not found", size, host);
MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH))) { ok1 = TlsRouteFirst(MBEDTLS_PK_ECKEY, ssl);
continue; ok2 = TlsRouteFirst(MBEDTLS_PK_RSA, ssl);
} }
if (ip == -1) { return ok1 || ok2 ? 0 : -1;
if (certs.p[i].cert->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
for (cur = &certs.p[i].cert->subject_alt_names; cur; cur = cur->next) {
if ((cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) ==
MBEDTLS_X509_SAN_DNS_NAME &&
SlicesEqualCase(host, size, cur->buf.p, cur->buf.len)) {
if (!TlsRouteCertificate(ssl, i, host, size)) rc = 0;
break;
}
}
} else {
for (name = &certs.p[i].cert->subject; name; name = name->next) {
if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) &&
SlicesEqualCase(host, size, name->val.p, name->val.len)) {
if (!TlsRouteCertificate(ssl, i, host, size)) rc = 0;
break;
}
}
}
} else if (certs.p[i].cert->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
for (cur = &certs.p[i].cert->subject_alt_names; cur; cur = cur->next) {
if ((cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) ==
MBEDTLS_X509_SAN_IP_ADDRESS &&
cur->buf.len == 4 && ip == READ32BE(cur->buf.p)) {
if (!TlsRouteCertificate(ssl, i, host, size)) rc = 0;
break;
}
}
}
}
if (rc) VERBOSEF("TlsRoute(%`'.*s) not found", size, host);
return rc;
} }
static bool TlsSetup(void) { static bool TlsSetup(void) {
@ -1872,19 +1866,19 @@ static void LoadCertificates(void) {
certs.p[i].cert, MBEDTLS_OID_SERVER_AUTH, certs.p[i].cert, MBEDTLS_OID_SERVER_AUTH,
MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH))) { MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH))) {
LogCertificate("using server certificate", certs.p[i].cert); LogCertificate("using server certificate", certs.p[i].cert);
UseCertificate(&conf, certs.p + i); UseCertificate(&conf, certs.p + i, "server");
havecert = true; havecert = true;
} }
if (!mbedtls_x509_crt_check_extended_key_usage( if (!mbedtls_x509_crt_check_extended_key_usage(
certs.p[i].cert, MBEDTLS_OID_CLIENT_AUTH, certs.p[i].cert, MBEDTLS_OID_CLIENT_AUTH,
MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH))) { MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH))) {
LogCertificate("using client certificate", certs.p[i].cert); LogCertificate("using client certificate", certs.p[i].cert);
UseCertificate(&confcli, certs.p + i); UseCertificate(&confcli, certs.p + i, "client");
haveclientcert = true; haveclientcert = true;
} }
} }
} }
if (!havecert || !haveclientcert) { if (!havecert) {
if ((ksk = GetKeySigningKey()).key) { if ((ksk = GetKeySigningKey()).key) {
DEBUGF("generating ssl certificates using %`'s", DEBUGF("generating ssl certificates using %`'s",
gc(FormatX509Name(&ksk.cert->subject))); gc(FormatX509Name(&ksk.cert->subject)));
@ -1898,14 +1892,14 @@ static void LoadCertificates(void) {
} }
#ifdef MBEDTLS_ECP_C #ifdef MBEDTLS_ECP_C
ecp = GenerateEcpCertificate(ksk.key ? &ksk : 0); ecp = GenerateEcpCertificate(ksk.key ? &ksk : 0);
if (!havecert) UseCertificate(&conf, &ecp); if (!havecert) UseCertificate(&conf, &ecp, "server");
if (!haveclientcert) UseCertificate(&confcli, &ecp); if (!haveclientcert && ksk.key) UseCertificate(&confcli, &ecp, "client");
AppendCert(ecp.cert, ecp.key); AppendCert(ecp.cert, ecp.key);
#endif #endif
#ifdef MBEDTLS_RSA_C #ifdef MBEDTLS_RSA_C
rsa = GenerateRsaCertificate(ksk.key ? &ksk : 0); rsa = GenerateRsaCertificate(ksk.key ? &ksk : 0);
if (!havecert) UseCertificate(&conf, &rsa); if (!havecert) UseCertificate(&conf, &rsa, "server");
if (!haveclientcert) UseCertificate(&confcli, &rsa); if (!haveclientcert && ksk.key) UseCertificate(&confcli, &rsa, "client");
AppendCert(rsa.cert, rsa.key); AppendCert(rsa.cert, rsa.key);
#endif #endif
} }
@ -2409,11 +2403,12 @@ static void AppendLogo(void) {
char *p, *q; char *p, *q;
struct Asset *a; struct Asset *a;
if ((a = GetAsset("/redbean.png", 12)) && (p = LoadAsset(a, &n))) { if ((a = GetAsset("/redbean.png", 12)) && (p = LoadAsset(a, &n))) {
q = EncodeBase64(p, n, &n); if ((q = EncodeBase64(p, n, &n))) {
Append("<img alt=\"[logo]\" src=\"data:image/png;base64,"); appends(&outbuf, "<img alt=\"[logo]\" src=\"data:image/png;base64,");
AppendData(q, n); appendd(&outbuf, q, n);
Append("\">\r\n"); appends(&outbuf, "\">\r\n");
free(q); free(q);
}
free(p); free(p);
} }
} }
@ -2438,15 +2433,17 @@ static ssize_t Send(struct iovec *iov, int iovlen) {
static char *CommitOutput(char *p) { static char *CommitOutput(char *p) {
uint32_t crc; uint32_t crc;
size_t outbuflen;
if (!contentlength) { if (!contentlength) {
if (istext && outbuf.n >= 100) { outbuflen = appendz(outbuf).i;
if (istext && outbuflen >= 100) {
p = stpcpy(p, "Vary: Accept-Encoding\r\n"); p = stpcpy(p, "Vary: Accept-Encoding\r\n");
if (!IsTiny() && ClientAcceptsGzip()) { if (!IsTiny() && ClientAcceptsGzip()) {
gzipped = true; gzipped = true;
crc = crc32_z(0, outbuf.p, outbuf.n); crc = crc32_z(0, outbuf, outbuflen);
WRITE32LE(gzip_footer + 0, crc); WRITE32LE(gzip_footer + 0, crc);
WRITE32LE(gzip_footer + 4, outbuf.n); WRITE32LE(gzip_footer + 4, outbuflen);
content = FreeLater(Deflate(outbuf.p, outbuf.n, &contentlength)); content = FreeLater(Deflate(outbuf, outbuflen, &contentlength));
DropOutput(); DropOutput();
} else { } else {
UseOutput(); UseOutput();
@ -2463,11 +2460,11 @@ static char *CommitOutput(char *p) {
static char *ServeDefaultErrorPage(char *p, unsigned code, const char *reason) { static char *ServeDefaultErrorPage(char *p, unsigned code, const char *reason) {
p = AppendContentType(p, "text/html; charset=ISO-8859-1"); p = AppendContentType(p, "text/html; charset=ISO-8859-1");
reason = FreeLater(EscapeHtml(reason, -1, 0)); reason = FreeLater(EscapeHtml(reason, -1, 0));
Append("\ appends(&outbuf, "\
<!doctype html>\r\n\ <!doctype html>\r\n\
<title>"); <title>");
Append("%d %s", code, reason); appendf(&outbuf, "%d %s", code, reason);
Append("\ appendf(&outbuf, "\
</title>\r\n\ </title>\r\n\
<style>\r\n\ <style>\r\n\
html { color: #111; font-family: sans-serif; }\r\n\ html { color: #111; font-family: sans-serif; }\r\n\
@ -2475,8 +2472,8 @@ img { vertical-align: middle; }\r\n\
</style>\r\n\ </style>\r\n\
<h1>\r\n"); <h1>\r\n");
AppendLogo(); AppendLogo();
Append("%d %s\r\n", code, reason); appendf(&outbuf, "%d %s\r\n", code, reason);
Append("</h1>\r\n"); appends(&outbuf, "</h1>\r\n");
UseOutput(); UseOutput();
return p; return p;
} }
@ -2486,7 +2483,7 @@ static char *ServeErrorImpl(unsigned code, const char *reason) {
char *p, *s; char *p, *s;
struct Asset *a; struct Asset *a;
LockInc(&shared->c.errors); LockInc(&shared->c.errors);
ClearOutput(); DropOutput();
p = SetStatus(code, reason); p = SetStatus(code, reason);
s = xasprintf("/%d.html", code); s = xasprintf("/%d.html", code);
a = GetAsset(s, strlen(s)); a = GetAsset(s, strlen(s));
@ -2868,7 +2865,7 @@ static char *ServeListing(void) {
size_t i, n, pathlen, rn[6]; size_t i, n, pathlen, rn[6];
LockInc(&shared->c.listingrequests); LockInc(&shared->c.listingrequests);
if (msg.method != kHttpGet && msg.method != kHttpHead) return BadMethod(); if (msg.method != kHttpGet && msg.method != kHttpHead) return BadMethod();
Append("\ appends(&outbuf, "\
<!doctype html>\r\n\ <!doctype html>\r\n\
<meta charset=\"utf-8\">\r\n\ <meta charset=\"utf-8\">\r\n\
<title>redbean zip listing</title>\r\n\ <title>redbean zip listing</title>\r\n\
@ -2885,9 +2882,10 @@ td { padding-right: 3em; }\r\n\
<header><h1>\r\n"); <header><h1>\r\n");
AppendLogo(); AppendLogo();
rp[0] = EscapeHtml(brand, -1, &rn[0]); rp[0] = EscapeHtml(brand, -1, &rn[0]);
AppendData(rp[0], rn[0]); appendd(&outbuf, rp[0], rn[0]);
free(rp[0]); free(rp[0]);
Append("</h1>\r\n" appendf(&outbuf,
"</h1>\r\n"
"<div class=\"eocdcomment\">%.*s</div>\r\n" "<div class=\"eocdcomment\">%.*s</div>\r\n"
"<hr>\r\n" "<hr>\r\n"
"</header>\r\n" "</header>\r\n"
@ -2925,14 +2923,16 @@ td { padding-right: 3em; }\r\n\
iso8601(tb, &tm); iso8601(tb, &tm);
if (IsCompressionMethodSupported(ZIP_CFILE_COMPRESSIONMETHOD(zcf)) && if (IsCompressionMethodSupported(ZIP_CFILE_COMPRESSIONMETHOD(zcf)) &&
IsAcceptablePath(path, pathlen)) { IsAcceptablePath(path, pathlen)) {
Append("<a href=\"%.*s\">%-*.*s</a> %s %0*o %4s %,*ld %'s\r\n", appendf(&outbuf,
rn[2], rp[2], w[0], rn[4], rp[4], tb, w[1], GetZipCfileMode(zcf), "<a href=\"%.*s\">%-*.*s</a> %s %0*o %4s %,*ld %'s\r\n",
DescribeCompressionRatio(rb, zcf), w[2], rn[2], rp[2], w[0], rn[4], rp[4], tb, w[1],
GetZipCfileMode(zcf), DescribeCompressionRatio(rb, zcf), w[2],
GetZipCfileUncompressedSize(zcf), rp[3]); GetZipCfileUncompressedSize(zcf), rp[3]);
} else { } else {
Append("%-*.*s %s %0*o %4s %,*ld %'s\r\n", w[0], rn[4], rp[4], tb, appendf(&outbuf, "%-*.*s %s %0*o %4s %,*ld %'s\r\n", w[0], rn[4],
w[1], GetZipCfileMode(zcf), DescribeCompressionRatio(rb, zcf), rp[4], tb, w[1], GetZipCfileMode(zcf),
w[2], GetZipCfileUncompressedSize(zcf), rp[3]); DescribeCompressionRatio(rb, zcf), w[2],
GetZipCfileUncompressedSize(zcf), rp[3]);
} }
free(rp[4]); free(rp[4]);
free(rp[3]); free(rp[3]);
@ -2942,42 +2942,44 @@ td { padding-right: 3em; }\r\n\
} }
free(path); free(path);
} }
Append("</pre><footer><hr>\r\n"); appends(&outbuf, "\
Append("<table border=\"0\"><tr>\r\n"); </pre><footer><hr>\r\n\
Append("<td valign=\"top\">\r\n"); <table border=\"0\"><tr>\r\n\
Append("<a href=\"/statusz\">/statusz</a>\r\n"); <td valign=\"top\">\r\n\
<a href=\"/statusz\">/statusz</a>\r\n\
");
if (shared->c.connectionshandled) { if (shared->c.connectionshandled) {
Append("says your redbean<br>\r\n"); appends(&outbuf, "says your redbean<br>\r\n");
AppendResourceReport(&shared->children, "<br>\r\n"); AppendResourceReport(&outbuf, &shared->children, "<br>\r\n");
} }
Append("<td valign=\"top\">\r\n"); appends(&outbuf, "<td valign=\"top\">\r\n");
and = ""; and = "";
x = nowl() - startserver; x = nowl() - startserver;
y = ldiv(x, 24L * 60 * 60); y = ldiv(x, 24L * 60 * 60);
if (y.quot) { if (y.quot) {
Append("%,ld day%s ", y.quot, y.quot == 1 ? "" : "s"); appendf(&outbuf, "%,ld day%s ", y.quot, y.quot == 1 ? "" : "s");
and = "and "; and = "and ";
} }
y = ldiv(y.rem, 60 * 60); y = ldiv(y.rem, 60 * 60);
if (y.quot) { if (y.quot) {
Append("%,ld hour%s ", y.quot, y.quot == 1 ? "" : "s"); appendf(&outbuf, "%,ld hour%s ", y.quot, y.quot == 1 ? "" : "s");
and = "and "; and = "and ";
} }
y = ldiv(y.rem, 60); y = ldiv(y.rem, 60);
if (y.quot) { if (y.quot) {
Append("%,ld minute%s ", y.quot, y.quot == 1 ? "" : "s"); appendf(&outbuf, "%,ld minute%s ", y.quot, y.quot == 1 ? "" : "s");
and = "and "; and = "and ";
} }
Append("%s%,ld second%s of operation<br>\r\n", and, y.rem, appendf(&outbuf, "%s%,ld second%s of operation<br>\r\n", and, y.rem,
y.rem == 1 ? "" : "s"); y.rem == 1 ? "" : "s");
x = shared->c.messageshandled; x = shared->c.messageshandled;
Append("%,ld message%s handled<br>\r\n", x, x == 1 ? "" : "s"); appendf(&outbuf, "%,ld message%s handled<br>\r\n", x, x == 1 ? "" : "s");
x = shared->c.connectionshandled; x = shared->c.connectionshandled;
Append("%,ld connection%s handled<br>\r\n", x, x == 1 ? "" : "s"); appendf(&outbuf, "%,ld connection%s handled<br>\r\n", x, x == 1 ? "" : "s");
x = shared->workers; x = shared->workers;
Append("%,ld connection%s active<br>\r\n", x, x == 1 ? "" : "s"); appendf(&outbuf, "%,ld connection%s active<br>\r\n", x, x == 1 ? "" : "s");
Append("</table>\r\n"); appends(&outbuf, "</table>\r\n");
Append("</footer>\r\n"); appends(&outbuf, "</footer>\r\n");
p = SetStatus(200, "OK"); p = SetStatus(200, "OK");
p = AppendContentType(p, "text/html"); p = AppendContentType(p, "text/html");
p = AppendCache(p, 0); p = AppendCache(p, 0);
@ -2989,11 +2991,11 @@ static const char *MergeNames(const char *a, const char *b) {
} }
static void AppendLong1(const char *a, long x) { static void AppendLong1(const char *a, long x) {
if (x) Append("%s: %ld\r\n", a, x); if (x) appendf(&outbuf, "%s: %ld\r\n", a, x);
} }
static void AppendLong2(const char *a, const char *b, long x) { static void AppendLong2(const char *a, const char *b, long x) {
if (x) Append("%s.%s: %ld\r\n", a, b, x); if (x) appendf(&outbuf, "%s.%s: %ld\r\n", a, b, x);
} }
static void AppendTimeval(const char *a, struct timeval *tv) { static void AppendTimeval(const char *a, struct timeval *tv) {
@ -3687,6 +3689,7 @@ static void LogBody(const char *d, const char *s, size_t n) {
} }
static int LuaFetch(lua_State *L) { static int LuaFetch(lua_State *L) {
#define ssl nope /* TODO(jart): make this file less huge */
char *p; char *p;
ssize_t rc; ssize_t rc;
bool usessl; bool usessl;
@ -3843,7 +3846,7 @@ static int LuaFetch(lua_State *L) {
bio->b = 0; bio->b = 0;
bio->c = -1; bio->c = -1;
mbedtls_ssl_set_bio(&sslcli, bio, TlsSend, 0, TlsRecvImpl); mbedtls_ssl_set_bio(&sslcli, bio, TlsSend, 0, TlsRecvImpl);
while ((ret = mbedtls_ssl_handshake(&ssl))) { while ((ret = mbedtls_ssl_handshake(&sslcli))) {
switch (ret) { switch (ret) {
case MBEDTLS_ERR_SSL_WANT_READ: case MBEDTLS_ERR_SSL_WANT_READ:
break; break;
@ -3856,7 +3859,8 @@ static int LuaFetch(lua_State *L) {
} }
LockInc(&shared->c.sslhandshakes); LockInc(&shared->c.sslhandshakes);
VERBOSEF("SHAKEN %s:%s %s %s", host, port, VERBOSEF("SHAKEN %s:%s %s %s", host, port,
mbedtls_ssl_get_ciphersuite(&ssl), mbedtls_ssl_get_version(&ssl)); mbedtls_ssl_get_ciphersuite(&sslcli),
mbedtls_ssl_get_version(&sslcli));
} }
/* /*
@ -4003,13 +4007,13 @@ static int LuaFetch(lua_State *L) {
Finished: Finished:
if (paylen && logbodies) LogBody("received", inbuf.p + hdrsize, paylen); if (paylen && logbodies) LogBody("received", inbuf.p + hdrsize, paylen);
LOGF("FETCH %s HTTP%02d %d %s %`'.*s", method, msg.version, msg.status, urlarg, LOGF("FETCH %s HTTP%02d %d %s %`'.*s", method, msg.version, msg.status,
HeaderLength(kHttpServer), HeaderData(kHttpServer)); urlarg, HeaderLength(kHttpServer), HeaderData(kHttpServer));
if (followredirect && HasHeader(kHttpLocation) && if (followredirect && HasHeader(kHttpLocation) &&
(msg.status == 301 || msg.status == 308 || // permanent redirects (msg.status == 301 || msg.status == 308 || // permanent redirects
msg.status == 302 || msg.status == 307 || // temporary redirects msg.status == 302 || msg.status == 307 || // temporary redirects
msg.status == 303 // see other; non-GET changes to GET, body lost msg.status == 303 /* see other; non-GET changes to GET, body lost */) &&
) && numredirects < maxredirects) { numredirects < maxredirects) {
// if 303, then remove body and set method to GET // if 303, then remove body and set method to GET
if (msg.status == 303) { if (msg.status == 303) {
body = ""; body = "";
@ -4058,6 +4062,7 @@ VerifyFailed:
LuaThrowTlsError( LuaThrowTlsError(
L, gc(DescribeSslVerifyFailure(sslcli.session_negotiate->verify_result)), L, gc(DescribeSslVerifyFailure(sslcli.session_negotiate->verify_result)),
ret); ret);
#undef ssl
} }
static int LuaGetDate(lua_State *L) { static int LuaGetDate(lua_State *L) {
@ -4496,7 +4501,7 @@ static int LuaWrite(lua_State *L) {
const char *data; const char *data;
if (!lua_isnil(L, 1)) { if (!lua_isnil(L, 1)) {
data = luaL_checklstring(L, 1, &size); data = luaL_checklstring(L, 1, &size);
AppendData(data, size); appendd(&outbuf, data, size);
} }
return 0; return 0;
} }
@ -5173,7 +5178,7 @@ static int LuaRe(lua_State *L) {
return 1; return 1;
} }
static bool LuaRun(const char *path) { static bool LuaRun(const char *path, bool mandatory) {
size_t pathlen; size_t pathlen;
struct Asset *a; struct Asset *a;
const char *code; const char *code;
@ -5184,8 +5189,12 @@ static bool LuaRun(const char *path) {
effectivepath.n = pathlen; effectivepath.n = pathlen;
DEBUGF("LuaRun(%`'s)", path); DEBUGF("LuaRun(%`'s)", path);
if (luaL_dostring(L, code) != LUA_OK) { if (luaL_dostring(L, code) != LUA_OK) {
if (mandatory) {
FATALF("%s %s", path, lua_tostring(L, -1));
} else {
WARNF("%s %s", path, lua_tostring(L, -1)); WARNF("%s %s", path, lua_tostring(L, -1));
} }
}
free(code); free(code);
} }
} }
@ -5341,9 +5350,21 @@ static void LuaSetConstant(lua_State *L, const char *s, long x) {
lua_setglobal(L, s); lua_setglobal(L, s);
} }
static char *GetDefaultLuaPath(void) {
char *s;
size_t i;
for (s = 0, i = 0; i < stagedirs.n; ++i) {
appendf(&s, "%s/.lua/?.lua;%s/.lua/?/init.lua;", stagedirs.p[i].s,
stagedirs.p[i].s);
}
appends(&s, "zip:.lua/?.lua;zip:.lua/?/init.lua");
return s;
}
static void LuaInit(void) { static void LuaInit(void) {
#ifndef STATIC #ifndef STATIC
size_t i; size_t i;
g_lua_path_default = GetDefaultLuaPath();
L = luaL_newstate(); L = luaL_newstate();
luaL_openlibs(L); luaL_openlibs(L);
for (i = 0; i < ARRAYLEN(kLuaLibs); ++i) { for (i = 0; i < ARRAYLEN(kLuaLibs); ++i) {
@ -5361,7 +5382,7 @@ static void LuaInit(void) {
LuaSetConstant(L, "kLogWarn", kLogWarn); LuaSetConstant(L, "kLogWarn", kLogWarn);
LuaSetConstant(L, "kLogError", kLogError); LuaSetConstant(L, "kLogError", kLogError);
LuaSetConstant(L, "kLogFatal", kLogFatal); LuaSetConstant(L, "kLogFatal", kLogFatal);
if (LuaRun("/.init.lua")) { if (LuaRun("/.init.lua", true)) {
hasonhttprequest = IsHookDefined("OnHttpRequest"); hasonhttprequest = IsHookDefined("OnHttpRequest");
hasonclientconnection = IsHookDefined("OnClientConnection"); hasonclientconnection = IsHookDefined("OnClientConnection");
hasonprocesscreate = IsHookDefined("OnProcessCreate"); hasonprocesscreate = IsHookDefined("OnProcessCreate");
@ -5376,7 +5397,7 @@ static void LuaInit(void) {
static void LuaReload(void) { static void LuaReload(void) {
#ifndef STATIC #ifndef STATIC
if (!LuaRun("/.reload.lua")) { if (!LuaRun("/.reload.lua", false)) {
DEBUGF("no /.reload.lua defined"); DEBUGF("no /.reload.lua defined");
} }
#endif #endif
@ -5580,7 +5601,7 @@ static void HandleHeartbeat(void) {
Reindex(); Reindex();
getrusage(RUSAGE_SELF, &shared->server); getrusage(RUSAGE_SELF, &shared->server);
#ifndef STATIC #ifndef STATIC
LuaRun("/.heartbeat.lua"); LuaRun("/.heartbeat.lua", false);
CollectGarbage(); CollectGarbage();
#endif #endif
for (i = 0; i < servers.n; ++i) { for (i = 0; i < servers.n; ++i) {
@ -6156,13 +6177,14 @@ static bool HandleMessage(void) {
} }
static void InitRequest(void) { static void InitRequest(void) {
assert(!outbuf);
frags = 0; frags = 0;
outbuf = 0;
gzipped = 0; gzipped = 0;
branded = 0; branded = 0;
content = 0; content = 0;
msgsize = 0; msgsize = 0;
loops.n = 0; loops.n = 0;
outbuf.n = 0;
generator = 0; generator = 0;
luaheaderp = 0; luaheaderp = 0;
contentlength = 0; contentlength = 0;
@ -6614,9 +6636,9 @@ static void MemDestroy(void) {
Free(&unmaplist.p), unmaplist.n = 0; Free(&unmaplist.p), unmaplist.n = 0;
Free(&freelist.p), freelist.n = 0; Free(&freelist.p), freelist.n = 0;
Free(&servers.p), servers.n = 0; Free(&servers.p), servers.n = 0;
Free(&outbuf.p), outbuf.n = 0;
Free(&hdrbuf.p), hdrbuf.n = 0; Free(&hdrbuf.p), hdrbuf.n = 0;
Free(&inbuf.p), inbuf.n = 0; Free(&inbuf.p), inbuf.n = 0;
Free(&outbuf);
FreeStrings(&stagedirs); FreeStrings(&stagedirs);
FreeStrings(&hidepaths); FreeStrings(&hidepaths);
Free(&launchbrowser); Free(&launchbrowser);