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]) {
x = h[i];
x /= n;
e += x * log2(1 / x);
e += x * log(x);
}
}
e = -(e / M_LN2);
}
return e;
}

View file

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

View file

@ -1,5 +1,5 @@
#ifndef COSMOPOLITAN_LIBC_STDIO_APPEND_INTERNAL_H_
#define COSMOPOLITAN_LIBC_STDIO_APPEND_INTERNAL_H_
#ifndef COSMOPOLITAN_LIBC_STDIO_APPEND_H_
#define COSMOPOLITAN_LIBC_STDIO_APPEND_H_
#include "libc/fmt/pflink.h"
#define APPEND_COOKIE 21578
@ -8,22 +8,23 @@
COSMOPOLITAN_C_START_
struct appendz {
size_t i; /* data size */
size_t n; /* allocation size */
size_t i;
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 *);
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__)
#define appendf(BUF, FMT, ...) (appendf)(BUF, PFLINK(FMT), ##__VA_ARGS__)
#define vappendf(BUF, FMT, VA) (vappendf)(BUF, PFLINK(FMT), VA)
#define appendf(BUF, FMT, ...) appendf(BUF, PFLINK(FMT), ##__VA_ARGS__)
#define vappendf(BUF, FMT, VA) vappendf(BUF, PFLINK(FMT), VA)
#endif
COSMOPOLITAN_C_END_
#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)
/**
* 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;
struct appendz z;
assert(b);
z = appendz((p = *b));
if (ROUNDUP(z.i + l + 1, 8) + W > z.n) {
if (!z.n) z.n = W * 2;

View file

@ -19,9 +19,16 @@
#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;
va_list va;
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"
/**
* 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));
}

View file

@ -19,15 +19,33 @@
#include "libc/bits/bits.h"
#include "libc/nexgen32e/bsr.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];
unsigned l;
if (!w) return 0;
unsigned n = 1;
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.
*
* @return i is number of bytes stored in buffer
* @return n is number of bytes in allocation
*/
struct appendz appendz(char *p) {
struct appendz z;

View file

@ -55,6 +55,10 @@ o/$(MODE)/libc/stdio/fputc.o: \
OVERRIDE_CFLAGS += \
-O3
o//libc/stdio/appendw.o: \
OVERRIDE_CFLAGS += \
-O2
LIBC_STDIO_LIBS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)))
LIBC_STDIO_SRCS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_SRCS))
LIBC_STDIO_HDRS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_HDRS))

View file

@ -25,9 +25,9 @@
#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;
int r, s;
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) {
char *b = 0;
appendf(&b, "hello ");
ASSERT_NE(-1, appendf(&b, "hello "));
EXPECT_EQ(6, appendz(b).i);
EXPECT_EQ(0, b[appendz(b).i]);
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(0, b[appendz(b).i]);
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(0, b[appendz(b).i]);
EXPECT_EQ(13, strlen(b));
EXPECT_EQ(0, b[13]);
EXPECT_EQ(0, b[14]);
@ -37,12 +40,17 @@ TEST(vappendf, test) {
free(b);
}
TEST(vappends, test) {
TEST(appends, test) {
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(0, b[appendz(b).i]);
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, strlen(b));
EXPECT_EQ(0, b[13]);
@ -50,6 +58,69 @@ TEST(vappends, test) {
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) {
const char t[] = {0};
char *b = 0;
@ -57,6 +128,8 @@ BENCH(vappendf, bench) {
free(b), b = 0;
EZBENCH2("appends", donothing, appends(&b, "1"));
free(b), b = 0;
EZBENCH2("appendw", donothing, appendw(&b, 'B'));
free(b), b = 0;
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/lualib.h"
const char *g_lua_path_default = LUA_PATH_DEFAULT;
/* 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) {
createclibstable(L);
luaL_newlib(L, pk_funcs); /* create 'package' table */
createsearcherstable(L);
/* 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);
/* store config information */
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 @@
/*
** $Id: 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
#ifndef COSMOPOLITAN_THIRD_PARTY_LUA_LUA_H_
#define COSMOPOLITAN_THIRD_PARTY_LUA_LUA_H_
#include "third_party/lua/luaconf.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/* clang-format off */
#define LUA_VERSION_MAJOR "5"
@ -489,29 +482,8 @@ struct lua_Debug {
/* }====================================================================== */
extern const char *g_lua_path_default;
/******************************************************************************
* Copyright (C) 1994-2021 Lua.org, PUC-Rio.
*
* 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
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_THIRD_PARTY_LUA_LUA_H_ */

View file

@ -60,6 +60,11 @@ o/$(MODE)/third_party/lua/lauxlib.o: \
OVERRIDE_CFLAGS += \
-DSTACK_FRAME_UNLIMITED
$(THIRD_PARTY_LUA_OBJS): \
OVERRIDE_CFLAGS += \
-ffunction-sections \
-fdata-sections
.PHONY: o/$(MODE)/third_party/lua
o/$(MODE)/third_party/lua: \
$(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
#define luaconf_h
#define LUA_USE_POSIX
#include "libc/assert.h"
#include "libc/dce.h"
#include "libc/fmt/fmt.h"
#include "libc/limits.h"
#include "third_party/gdtoa/gdtoa.h"
#define LUA_USE_POSIX
/* clang-format off */
/*
@ -193,63 +189,20 @@
*/
#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_LDIR 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"
#endif
#if !defined(LUA_CPATH_DEFAULT)
#define LUA_CPATH_DEFAULT \
LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"
#endif
#endif /* } */
#define LUA_PATH_DEFAULT LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" "./?.lua;" "./?/init.lua"
#define LUA_CPATH_DEFAULT LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"
/*
@@ LUA_DIRSEP is the directory separator (for submodules).
** CHANGE it if your machine does not use "/" as the directory separator
** and is not Windows. (On Windows Lua automatically uses "\".)
*/
#if !defined(LUA_DIRSEP)
#if defined(_WIN32)
#define LUA_DIRSEP "\\"
#else
#define LUA_DIRSEP "/"
#endif
#endif
/* }================================================================== */
@ -269,20 +222,8 @@
** the libraries, you may want to use the following definition (define
** 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
#endif /* } */
/*
** 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
** default definition.
*/
#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
defined(__ELF__) /* { */
#define LUAI_FUNC /* __attribute__((visibility("internal"))) */ extern
#else /* }{ */
#define LUAI_FUNC extern
#endif /* } */
#define LUAI_DDEC(dec) LUAI_FUNC dec
#define LUAI_DDEF /* empty */
@ -710,8 +646,7 @@
@@ LUA_USE_APICHECK turns on several consistency checks on the C API.
** Define it as a help when debugging C code.
*/
#if defined(LUA_USE_APICHECK)
#include <assert.h>
#if IsModeDbg()
#define luai_apicheck(l,e) assert(e)
#endif

View file

@ -2,6 +2,7 @@
#define MBEDTLS_CONFIG_H_
#include "libc/dce.h"
/* /\* uncomment for testing old cpu code paths *\/ */
/* #include "libc/nexgen32e/x86feature.h" */
/* #undef X86_HAVE */
/* #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] );
}
bool mbedtls_p384_gte( uint64_t p[7] )
static bool
mbedtls_p384_gte( uint64_t p[7] )
{
return( (((int64_t)p[6] > 0) |
(!p[6] &
(p[5] > 0xffffffffffffffff |
(p[5] == 0xffffffffffffffff &
(p[4] > 0xffffffffffffffff |
(p[4] == 0xffffffffffffffff &
(p[3] > 0xffffffffffffffff |
(p[3] == 0xffffffffffffffff &
(p[2] > 0xfffffffffffffffe |
(p[2] == 0xfffffffffffffffe &
(p[1] > 0xffffffff00000000 |
(p[1] == 0xffffffff00000000 &
(p[0] > 0x00000000ffffffff |
((p[5] > 0xffffffffffffffff) |
((p[5] == 0xffffffffffffffff) &
((p[4] > 0xffffffffffffffff) |
((p[4] == 0xffffffffffffffff) &
((p[3] > 0xffffffffffffffff) |
((p[3] == 0xffffffffffffffff) &
((p[2] > 0xfffffffffffffffe) |
((p[2] == 0xfffffffffffffffe) &
((p[1] > 0xffffffff00000000) |
((p[1] == 0xffffffff00000000) &
((p[0] > 0x00000000ffffffff) |
(p[0] == 0x00000000ffffffff)))))))))))))) );
}
@ -128,7 +129,8 @@ mbedtls_p384_gro( uint64_t p[7] )
#endif
}
void mbedtls_p384_rum( uint64_t p[7] )
static inline void
mbedtls_p384_rum( uint64_t p[7] )
{
while( mbedtls_p384_gte( p ) )
mbedtls_p384_red( p );
@ -142,9 +144,7 @@ void mbedtls_p384_mod( uint64_t X[12] )
mbedtls_p384_gro(X);
} while( (int64_t)X[6] < 0 );
} else {
while( mbedtls_p384_gte(X) ){
mbedtls_p384_red(X);
}
mbedtls_p384_rum(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 *,
mbedtls_ecp_point *[], size_t );
void mbedtls_p384_rum( uint64_t p[7] );
void mbedtls_p384_mod( uint64_t X[12] );
#endif /* COSMOPOLITAN_THIRD_PARTY_MBEDTLS_ECP_INTERNAL_H_ */

View file

@ -27,6 +27,8 @@
#include "third_party/mbedtls/math.h"
#ifdef MBEDTLS_ECP_C
/*P=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff*/
int ecp_mod_p384_old(mbedtls_mpi *);
int GetEntropy(void *c, unsigned char *p, size_t n) {
@ -97,14 +99,6 @@ TEST(secp384r1, needsDownwardCorrection) {
TEST(secp384r1, needsUpwardCorrection) {
int i;
uint64_t P[6] = {
0x00000000ffffffff, //
0xffffffff00000000, //
0xfffffffffffffffe, //
0xffffffffffffffff, //
0xffffffffffffffff, //
0xffffffffffffffff, //
};
uint64_t X[12] = {
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) {
mbedtls_mpi A;
mbedtls_mpi_init(&A);

View file

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

View file

@ -244,7 +244,8 @@ SECURITY
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
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
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
@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
@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) -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

View file

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