diff --git a/net/http/encodelatin1.c b/net/http/encodelatin1.c index 17d7f35ac..924188c4e 100644 --- a/net/http/encodelatin1.c +++ b/net/http/encodelatin1.c @@ -30,7 +30,7 @@ * @param p is input value * @param n if -1 implies strlen * @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 * @error EILSEQ means UTF-8 found we can't or won't re-encode * @error ENOMEM means malloc() failed @@ -38,7 +38,12 @@ char *EncodeLatin1(const char *p, size_t n, size_t *z, int f) { int c; size_t i; + char t[256]; 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 (n == -1) n = p ? strlen(p) : 0; 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; } } - if (((f & kControlC1) && 0x80 <= c && c < 0xA0) || - ((f & kControlC0) && (c < 32 || c == 0x7F) && - !(c == '\t' || c == '\r' || c == '\n' || c == '\v')) || - ((f & kControlWs) && - (c == '\t' || c == '\r' || c == '\n' || c == '\v'))) { + if (t[c]) { goto Invalid; } *q++ = c; diff --git a/net/http/escape.h b/net/http/escape.h index 734082ad6..665ebb0de 100644 --- a/net/http/escape.h +++ b/net/http/escape.h @@ -28,7 +28,7 @@ char *EscapeFragment(const char *, size_t, size_t *); char *EscapeSegment(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 *DecodeLatin1(const char *, size_t, size_t *); char *EncodeLatin1(const char *, size_t, size_t *, int); diff --git a/net/http/hascontrolcodes.c b/net/http/hascontrolcodes.c index 7748bb48e..1ebc0e86e 100644 --- a/net/http/hascontrolcodes.c +++ b/net/http/hascontrolcodes.c @@ -16,11 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/errno.h" -#include "libc/intrin/pcmpgtb.h" -#include "libc/intrin/pmovmskb.h" -#include "libc/mem/mem.h" -#include "libc/stdio/stdio.h" +#include "libc/bits/likely.h" #include "libc/str/str.h" #include "libc/str/thompike.h" #include "net/http/escape.h" @@ -31,17 +27,21 @@ * @param p is input value * @param n if -1 implies strlen * @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() */ -bool HasControlCodes(const char *p, size_t n, int f) { - int c; +ssize_t HasControlCodes(const char *p, size_t n, int f) { + char t[256]; wint_t x, a, b; 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; for (i = 0; i < n;) { x = p[i++] & 0xff; - if (x >= 0300) { + if (UNLIKELY(x >= 0300)) { a = ThomPikeByte(x); m = ThomPikeLen(x) - 1; 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) || - ((f & kControlC0) && (x < 32 || x == 0x7F) && - !(x == '\t' || x == '\r' || x == '\n' || x == '\v')) || - ((f & kControlWs) && - (x == '\t' || x == '\r' || x == '\n' || x == '\v'))) { - return true; + if (x < 256 && t[x]) { + return i - 1; } } - return false; + return -1; } diff --git a/net/http/isacceptablepath.c b/net/http/isacceptablepath.c index 274074e0a..fa155ce20 100644 --- a/net/http/isacceptablepath.c +++ b/net/http/isacceptablepath.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/likely.h" #include "libc/str/str.h" #include "libc/str/thompike.h" #include "net/http/http.h" @@ -45,7 +46,7 @@ bool IsAcceptablePath(const char *data, size_t size) { e = p + size; while (p < e) { x = *p++ & 0xff; - if (x >= 0300) { + if (UNLIKELY(x >= 0300)) { a = ThomPikeByte(x); n = ThomPikeLen(x) - 1; if (p + n <= e) { diff --git a/test/net/http/hascontrolcodes_test.c b/test/net/http/hascontrolcodes_test.c index 26afa3a48..264bf0bd6 100644 --- a/test/net/http/hascontrolcodes_test.c +++ b/test/net/http/hascontrolcodes_test.c @@ -22,30 +22,30 @@ #include "net/http/escape.h" TEST(HasControlCodes, test) { - EXPECT_FALSE( - HasControlCodes(kHyperion, kHyperionSize, kControlC0 | kControlC1)); - EXPECT_TRUE(HasControlCodes("hi\1", -1, kControlC0)); - EXPECT_FALSE(HasControlCodes("hi\1", -1, kControlC1)); - EXPECT_FALSE(HasControlCodes("hi there", -1, 0)); - EXPECT_TRUE(HasControlCodes("hi\tthere", -1, kControlWs)); + EXPECT_EQ(-1, HasControlCodes(kHyperion, kHyperionSize, kControlC0)); + EXPECT_EQ(+2, HasControlCodes("hi\1", -1, kControlC0)); + EXPECT_EQ(-1, HasControlCodes("hi\1", -1, kControlC1)); + EXPECT_EQ(-1, HasControlCodes("hi there", -1, 0)); + EXPECT_NE(-1, HasControlCodes("hi\tthere", -1, kControlWs)); } TEST(HasControlCodes, testDoesUtf8) { - EXPECT_FALSE(HasControlCodes(u8"→", -1, kControlC0 | kControlC1)); - EXPECT_FALSE(HasControlCodes("\304\200", -1, kControlC0 | kControlC1)); - EXPECT_TRUE(HasControlCodes("\300\200", -1, kControlC0 | kControlC1)); - EXPECT_FALSE(HasControlCodes("\300\200", -1, kControlC1)); - EXPECT_TRUE(HasControlCodes("\302\202", -1, kControlC0 | kControlC1)); - EXPECT_TRUE(HasControlCodes("\302\202", -1, kControlC1)); - EXPECT_FALSE(HasControlCodes("\302\202", -1, kControlC0)); + EXPECT_EQ(-1, HasControlCodes(u8"→", -1, kControlC0 | kControlC1)); + EXPECT_EQ(-1, HasControlCodes("\304\200", -1, kControlC0 | kControlC1)); + EXPECT_NE(-1, HasControlCodes("\300\200", -1, kControlC0 | kControlC1)); + EXPECT_EQ(-1, HasControlCodes("\300\200", -1, kControlC1)); + EXPECT_NE(-1, HasControlCodes("\302\202", -1, kControlC0 | kControlC1)); + EXPECT_NE(-1, HasControlCodes("\302\202", -1, kControlC1)); + EXPECT_EQ(-1, HasControlCodes("\302\202", -1, kControlC0)); } TEST(HasControlCodes, testHasLatin1FallbackBehavior) { - EXPECT_TRUE(HasControlCodes("\202", -1, kControlWs | kControlC1)); - EXPECT_FALSE(HasControlCodes("\202", -1, kControlC0)); + EXPECT_NE(-1, HasControlCodes("\202", -1, kControlWs | kControlC1)); + EXPECT_EQ(-1, HasControlCodes("\202", -1, kControlC0)); } BENCH(HasControlCodes, bench) { - EZBENCH2("HasControlCodes", donothing, - HasControlCodes(kHyperion, kHyperionSize, kControlWs)); + EZBENCH2("HasControlCodes small", donothing, HasControlCodes("hello", -1, 0)); + EZBENCH2("HasControlCodes big", donothing, + HasControlCodes(kHyperion, kHyperionSize, kControlC1)); } diff --git a/tool/net/redbean.c b/tool/net/redbean.c index 510bbca7c..0ff6e3d0d 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -1125,7 +1125,7 @@ static void Daemonize(void) { if ((pid = fork()) > 0) _exit(0); umask(0); 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)); close(fd); } @@ -1695,7 +1695,7 @@ static void AppendLogo(void) { struct Asset *a; if ((a = GetAsset("/redbean.png", 12)) && (p = LoadAsset(a, &n))) { q = EncodeBase64(p, n, &n); - Append("\"[logo]\"\r\n"); free(q); @@ -2951,7 +2951,7 @@ static int LuaSetHeader(lua_State *L) { } switch (h) { case kHttpConnection: - if (evallen != 5 || memcmp(eval, "close", 5)) { + if (evallen != 5 || memcasecmp(eval, "close", 5)) { luaL_argerror(L, 2, "unsupported"); unreachable; } @@ -3162,7 +3162,7 @@ static int LuaHasControlCodes(lua_State *L) { const char *p; p = luaL_checklstring(L, 1, &n); f = LuaCheckControlFlags(L, 2); - lua_pushboolean(L, HasControlCodes(p, n, f)); + lua_pushboolean(L, HasControlCodes(p, n, f) != -1); return 1; } @@ -4530,9 +4530,6 @@ void RedBean(int argc, char *argv[], const char *prog) { xsigaction(SIGALRM, OnAlrm, 0, 0, 0); xsigaction(SIGPIPE, SIG_IGN, 0, 0, 0); /* TODO(jart): SIGXCPU and SIGXFSZ */ - if (setitimer(ITIMER_REAL, &kHeartbeat, NULL) == -1) { - heartless = true; - } server = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); CHECK_NE(-1, server); TuneSockets(); @@ -4557,6 +4554,9 @@ void RedBean(int argc, char *argv[], const char *prog) { fflush(stdout); } if (daemonize) Daemonize(); + if (setitimer(ITIMER_REAL, &kHeartbeat, NULL) == -1) { + heartless = true; + } UpdateCurrentDate(nowl()); freelist.c = 8; freelist.p = xcalloc(freelist.c, sizeof(*freelist.p)); diff --git a/tool/viz/life.c b/tool/viz/life.c index 672516b48..2965a67c0 100644 --- a/tool/viz/life.c +++ b/tool/viz/life.c @@ -428,6 +428,7 @@ static void OnUnzoom(long y, long x) { } static void OnMouseLeftDrag(long y, long x) { + int i; if (y == save_y && x == save_x) return; save_y = y; save_x = x; @@ -440,7 +441,10 @@ static void OnMouseLeftDrag(long y, long x) { if (erase) { Unset(y, x); } 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))); + } } }