Fix redbean date header in daemonize mode

This commit is contained in:
Justine Tunney 2021-05-02 11:11:26 -07:00
parent 1f2288be6e
commit 84001a246c
7 changed files with 51 additions and 49 deletions

View file

@ -30,7 +30,7 @@
* @param p is input value * @param p is input value
* @param n if -1 implies strlen * @param n if -1 implies strlen
* @param z if non-NULL receives output length * @param z if non-NULL receives output length
* @param f can kControlC0, kControlC1 to forbid * @param f can kControlC0, kControlC1, kControlWs to forbid
* @return allocated NUL-terminated buffer, or NULL w/ errno * @return allocated NUL-terminated buffer, or NULL w/ errno
* @error EILSEQ means UTF-8 found we can't or won't re-encode * @error EILSEQ means UTF-8 found we can't or won't re-encode
* @error ENOMEM means malloc() failed * @error ENOMEM means malloc() failed
@ -38,7 +38,12 @@
char *EncodeLatin1(const char *p, size_t n, size_t *z, int f) { char *EncodeLatin1(const char *p, size_t n, size_t *z, int f) {
int c; int c;
size_t i; size_t i;
char t[256];
char *r, *q; char *r, *q;
memset(t, 0, sizeof(t));
if (f & kControlC0) memset(t + 0x00, 1, 0x20 - 0x00), t[0x7F] = 1;
if (f & kControlC1) memset(t + 0x80, 1, 0xA0 - 0x80);
t['\t'] = t['\r'] = t['\n'] = t['\v'] = !!(f & kControlWs);
if (z) *z = 0; if (z) *z = 0;
if (n == -1) n = p ? strlen(p) : 0; if (n == -1) n = p ? strlen(p) : 0;
if ((q = r = malloc(n + 1))) { if ((q = r = malloc(n + 1))) {
@ -51,11 +56,7 @@ char *EncodeLatin1(const char *p, size_t n, size_t *z, int f) {
goto Invalid; goto Invalid;
} }
} }
if (((f & kControlC1) && 0x80 <= c && c < 0xA0) || if (t[c]) {
((f & kControlC0) && (c < 32 || c == 0x7F) &&
!(c == '\t' || c == '\r' || c == '\n' || c == '\v')) ||
((f & kControlWs) &&
(c == '\t' || c == '\r' || c == '\n' || c == '\v'))) {
goto Invalid; goto Invalid;
} }
*q++ = c; *q++ = c;

View file

@ -28,7 +28,7 @@ char *EscapeFragment(const char *, size_t, size_t *);
char *EscapeSegment(const char *, size_t, size_t *); char *EscapeSegment(const char *, size_t, size_t *);
char *EscapeJsStringLiteral(const char *, size_t, size_t *); char *EscapeJsStringLiteral(const char *, size_t, size_t *);
bool HasControlCodes(const char *, size_t, int); ssize_t HasControlCodes(const char *, size_t, int);
char *Underlong(const char *, size_t, size_t *); char *Underlong(const char *, size_t, size_t *);
char *DecodeLatin1(const char *, size_t, size_t *); char *DecodeLatin1(const char *, size_t, size_t *);
char *EncodeLatin1(const char *, size_t, size_t *, int); char *EncodeLatin1(const char *, size_t, size_t *, int);

View file

@ -16,11 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/errno.h" #include "libc/bits/likely.h"
#include "libc/intrin/pcmpgtb.h"
#include "libc/intrin/pmovmskb.h"
#include "libc/mem/mem.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/str/thompike.h" #include "libc/str/thompike.h"
#include "net/http/escape.h" #include "net/http/escape.h"
@ -31,17 +27,21 @@
* @param p is input value * @param p is input value
* @param n if -1 implies strlen * @param n if -1 implies strlen
* @param f can have kControlWs, kControlC0, kControlC1 to forbid * @param f can have kControlWs, kControlC0, kControlC1 to forbid
* @return true if forbidden characters were found * @return index of first forbidden character or -1
* @see VisualizeControlCodes() * @see VisualizeControlCodes()
*/ */
bool HasControlCodes(const char *p, size_t n, int f) { ssize_t HasControlCodes(const char *p, size_t n, int f) {
int c; char t[256];
wint_t x, a, b; wint_t x, a, b;
size_t i, j, m; size_t i, j, m;
memset(t, 0, sizeof(t));
if (f & kControlC0) memset(t + 0x00, 1, 0x20 - 0x00), t[0x7F] = 1;
if (f & kControlC1) memset(t + 0x80, 1, 0xA0 - 0x80);
t['\t'] = t['\r'] = t['\n'] = t['\v'] = !!(f & kControlWs);
if (n == -1) n = p ? strlen(p) : 0; if (n == -1) n = p ? strlen(p) : 0;
for (i = 0; i < n;) { for (i = 0; i < n;) {
x = p[i++] & 0xff; x = p[i++] & 0xff;
if (x >= 0300) { if (UNLIKELY(x >= 0300)) {
a = ThomPikeByte(x); a = ThomPikeByte(x);
m = ThomPikeLen(x) - 1; m = ThomPikeLen(x) - 1;
if (i + m <= n) { if (i + m <= n) {
@ -57,13 +57,9 @@ bool HasControlCodes(const char *p, size_t n, int f) {
} }
} }
} }
if (((f & kControlC1) && 0x80 <= x && x < 0xA0) || if (x < 256 && t[x]) {
((f & kControlC0) && (x < 32 || x == 0x7F) && return i - 1;
!(x == '\t' || x == '\r' || x == '\n' || x == '\v')) ||
((f & kControlWs) &&
(x == '\t' || x == '\r' || x == '\n' || x == '\v'))) {
return true;
} }
} }
return false; return -1;
} }

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/likely.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/str/thompike.h" #include "libc/str/thompike.h"
#include "net/http/http.h" #include "net/http/http.h"
@ -45,7 +46,7 @@ bool IsAcceptablePath(const char *data, size_t size) {
e = p + size; e = p + size;
while (p < e) { while (p < e) {
x = *p++ & 0xff; x = *p++ & 0xff;
if (x >= 0300) { if (UNLIKELY(x >= 0300)) {
a = ThomPikeByte(x); a = ThomPikeByte(x);
n = ThomPikeLen(x) - 1; n = ThomPikeLen(x) - 1;
if (p + n <= e) { if (p + n <= e) {

View file

@ -22,30 +22,30 @@
#include "net/http/escape.h" #include "net/http/escape.h"
TEST(HasControlCodes, test) { TEST(HasControlCodes, test) {
EXPECT_FALSE( EXPECT_EQ(-1, HasControlCodes(kHyperion, kHyperionSize, kControlC0));
HasControlCodes(kHyperion, kHyperionSize, kControlC0 | kControlC1)); EXPECT_EQ(+2, HasControlCodes("hi\1", -1, kControlC0));
EXPECT_TRUE(HasControlCodes("hi\1", -1, kControlC0)); EXPECT_EQ(-1, HasControlCodes("hi\1", -1, kControlC1));
EXPECT_FALSE(HasControlCodes("hi\1", -1, kControlC1)); EXPECT_EQ(-1, HasControlCodes("hi there", -1, 0));
EXPECT_FALSE(HasControlCodes("hi there", -1, 0)); EXPECT_NE(-1, HasControlCodes("hi\tthere", -1, kControlWs));
EXPECT_TRUE(HasControlCodes("hi\tthere", -1, kControlWs));
} }
TEST(HasControlCodes, testDoesUtf8) { TEST(HasControlCodes, testDoesUtf8) {
EXPECT_FALSE(HasControlCodes(u8"", -1, kControlC0 | kControlC1)); EXPECT_EQ(-1, HasControlCodes(u8"", -1, kControlC0 | kControlC1));
EXPECT_FALSE(HasControlCodes("\304\200", -1, kControlC0 | kControlC1)); EXPECT_EQ(-1, HasControlCodes("\304\200", -1, kControlC0 | kControlC1));
EXPECT_TRUE(HasControlCodes("\300\200", -1, kControlC0 | kControlC1)); EXPECT_NE(-1, HasControlCodes("\300\200", -1, kControlC0 | kControlC1));
EXPECT_FALSE(HasControlCodes("\300\200", -1, kControlC1)); EXPECT_EQ(-1, HasControlCodes("\300\200", -1, kControlC1));
EXPECT_TRUE(HasControlCodes("\302\202", -1, kControlC0 | kControlC1)); EXPECT_NE(-1, HasControlCodes("\302\202", -1, kControlC0 | kControlC1));
EXPECT_TRUE(HasControlCodes("\302\202", -1, kControlC1)); EXPECT_NE(-1, HasControlCodes("\302\202", -1, kControlC1));
EXPECT_FALSE(HasControlCodes("\302\202", -1, kControlC0)); EXPECT_EQ(-1, HasControlCodes("\302\202", -1, kControlC0));
} }
TEST(HasControlCodes, testHasLatin1FallbackBehavior) { TEST(HasControlCodes, testHasLatin1FallbackBehavior) {
EXPECT_TRUE(HasControlCodes("\202", -1, kControlWs | kControlC1)); EXPECT_NE(-1, HasControlCodes("\202", -1, kControlWs | kControlC1));
EXPECT_FALSE(HasControlCodes("\202", -1, kControlC0)); EXPECT_EQ(-1, HasControlCodes("\202", -1, kControlC0));
} }
BENCH(HasControlCodes, bench) { BENCH(HasControlCodes, bench) {
EZBENCH2("HasControlCodes", donothing, EZBENCH2("HasControlCodes small", donothing, HasControlCodes("hello", -1, 0));
HasControlCodes(kHyperion, kHyperionSize, kControlWs)); EZBENCH2("HasControlCodes big", donothing,
HasControlCodes(kHyperion, kHyperionSize, kControlC1));
} }

View file

@ -1125,7 +1125,7 @@ static void Daemonize(void) {
if ((pid = fork()) > 0) _exit(0); if ((pid = fork()) > 0) _exit(0);
umask(0); umask(0);
if (pidpath) { if (pidpath) {
fd = open(pidpath, O_CREAT | O_EXCL | O_WRONLY, 0644); fd = open(pidpath, O_CREAT | O_WRONLY, 0644);
write(fd, ibuf, uint64toarray_radix10(getpid(), ibuf)); write(fd, ibuf, uint64toarray_radix10(getpid(), ibuf));
close(fd); close(fd);
} }
@ -1695,7 +1695,7 @@ static void AppendLogo(void) {
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); q = EncodeBase64(p, n, &n);
Append("<img src=\"data:image/png;base64,"); Append("<img alt=\"[logo]\" src=\"data:image/png;base64,");
AppendData(q, n); AppendData(q, n);
Append("\">\r\n"); Append("\">\r\n");
free(q); free(q);
@ -2951,7 +2951,7 @@ static int LuaSetHeader(lua_State *L) {
} }
switch (h) { switch (h) {
case kHttpConnection: case kHttpConnection:
if (evallen != 5 || memcmp(eval, "close", 5)) { if (evallen != 5 || memcasecmp(eval, "close", 5)) {
luaL_argerror(L, 2, "unsupported"); luaL_argerror(L, 2, "unsupported");
unreachable; unreachable;
} }
@ -3162,7 +3162,7 @@ static int LuaHasControlCodes(lua_State *L) {
const char *p; const char *p;
p = luaL_checklstring(L, 1, &n); p = luaL_checklstring(L, 1, &n);
f = LuaCheckControlFlags(L, 2); f = LuaCheckControlFlags(L, 2);
lua_pushboolean(L, HasControlCodes(p, n, f)); lua_pushboolean(L, HasControlCodes(p, n, f) != -1);
return 1; return 1;
} }
@ -4530,9 +4530,6 @@ void RedBean(int argc, char *argv[], const char *prog) {
xsigaction(SIGALRM, OnAlrm, 0, 0, 0); xsigaction(SIGALRM, OnAlrm, 0, 0, 0);
xsigaction(SIGPIPE, SIG_IGN, 0, 0, 0); xsigaction(SIGPIPE, SIG_IGN, 0, 0, 0);
/* TODO(jart): SIGXCPU and SIGXFSZ */ /* TODO(jart): SIGXCPU and SIGXFSZ */
if (setitimer(ITIMER_REAL, &kHeartbeat, NULL) == -1) {
heartless = true;
}
server = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); server = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
CHECK_NE(-1, server); CHECK_NE(-1, server);
TuneSockets(); TuneSockets();
@ -4557,6 +4554,9 @@ void RedBean(int argc, char *argv[], const char *prog) {
fflush(stdout); fflush(stdout);
} }
if (daemonize) Daemonize(); if (daemonize) Daemonize();
if (setitimer(ITIMER_REAL, &kHeartbeat, NULL) == -1) {
heartless = true;
}
UpdateCurrentDate(nowl()); UpdateCurrentDate(nowl());
freelist.c = 8; freelist.c = 8;
freelist.p = xcalloc(freelist.c, sizeof(*freelist.p)); freelist.p = xcalloc(freelist.c, sizeof(*freelist.p));

View file

@ -428,6 +428,7 @@ static void OnUnzoom(long y, long x) {
} }
static void OnMouseLeftDrag(long y, long x) { static void OnMouseLeftDrag(long y, long x) {
int i;
if (y == save_y && x == save_x) return; if (y == save_y && x == save_x) return;
save_y = y; save_y = y;
save_x = x; save_x = x;
@ -440,7 +441,10 @@ static void OnMouseLeftDrag(long y, long x) {
if (erase) { if (erase) {
Unset(y, x); Unset(y, x);
} else { } else {
Set(y, x); for (i = 0; i < (2 << zoom); ++i) {
Set(y + (rand() % (zoom + 1)) - (rand() % (zoom + 1)),
x + (rand() % (zoom + 1)) - (rand() % (zoom + 1)));
}
} }
} }