Skip to content

Commit

Permalink
Improve overflow detection
Browse files Browse the repository at this point in the history
  • Loading branch information
jart committed Jul 4, 2023
1 parent caf97b1 commit 768e9bb
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 145 deletions.
38 changes: 20 additions & 18 deletions blink/blinkenlights.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "blink/blinkenlights.h"

#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
Expand All @@ -39,9 +41,9 @@

#include "blink/assert.h"
#include "blink/atomic.h"
#include "blink/bda.h"
#include "blink/biosrom.h"
#include "blink/bitscan.h"
#include "blink/blinkenlights.h"
#include "blink/breakpoint.h"
#include "blink/builtin.h"
#include "blink/bus.h"
Expand All @@ -67,7 +69,6 @@
#include "blink/panel.h"
#include "blink/pml4t.h"
#include "blink/pty.h"
#include "blink/bda.h"
#include "blink/rde.h"
#include "blink/signal.h"
#include "blink/sigwinch.h"
Expand Down Expand Up @@ -347,7 +348,7 @@ static bool alarmed;
static bool natural;
static bool mousemode;
static bool wantmetal;
static bool displayexec; /* 'D' -> DrawDisplayOnly during Exec() */
static bool displayexec; /* 'D' -> DrawDisplayOnly during Exec() */
static bool showhighsse;
static bool showprofile;
static bool readingteletype;
Expand Down Expand Up @@ -805,7 +806,7 @@ static void OnQ(void) {

static void OnV(void) {
int mode;
mode = vidya == kModePty? 3: kModePty;
mode = vidya == kModePty ? 3 : kModePty;
VidyaServiceSetMode(mode);
}

Expand Down Expand Up @@ -1379,14 +1380,14 @@ static void DrawTerminal(struct Panel *p) {

static void DrawDisplay(struct Panel *p) {
switch (vidya) {
case 0: // CGA 40x25 16-gray
case 1: // CGA 40x25 16-color
case 2: // CGA 80x25 16-gray
case 3: // CGA 80x25 16-color
case 0: // CGA 40x25 16-gray
case 1: // CGA 40x25 16-color
case 2: // CGA 80x25 16-gray
case 3: // CGA 80x25 16-color
DrawHr(&pan.displayhr, "COLOR GRAPHICS ADAPTER");
DrawCga(p, m->system->real + 0xb8000);
break;
case 7: // MDA 80x25 4-gray
case 7: // MDA 80x25 4-gray
DrawHr(&pan.displayhr, "MONOCHROME DISPLAY ADAPTER");
DrawMda(p, (u8(*)[80][2])(m->system->real + 0xb0000), pty->x, pty->y);
break;
Expand Down Expand Up @@ -2251,8 +2252,8 @@ static void HandleTerminalResize(void) {
void HandleAppReadInterrupt(bool errflag) {
LOGF("HandleAppReadInterrupt");
if (errflag) {
exitcode = 0;
action |= EXIT;
exitcode = 0;
action |= EXIT;
}
if (action & ALARM) {
HandleAlarm();
Expand Down Expand Up @@ -2464,7 +2465,7 @@ void DrawDisplayOnly(void) {
if (displayexec && y) AppendStr(&b, "\r\n");
if (tly <= y && y < tly + yn) {
if (!displayexec) {
sprintf(buf, "\033[%d;%dH", y+1, tlx+1);
sprintf(buf, "\033[%d;%dH", y + 1, tlx + 1);
AppendStr(&b, buf);
} else {
for (i = 0; i < tlx; ++i) {
Expand Down Expand Up @@ -2751,8 +2752,9 @@ static void OnLongBranch(struct Machine *m) {
#ifndef DISABLE_ROM
static void OnRomWriteAttempt(struct Machine *m, u8 *r) {
int w = GetAddrHexWidth();
LOGF("attempt to write to rom address %0*tx @ %0*" PRIx64,
w, r - m->system->real, w, GetPc(m));
(void)w;
LOGF("attempt to write to rom address %0*tx @ %0*" PRIx64, w,
r - m->system->real, w, GetPc(m));
}
#endif

Expand Down Expand Up @@ -3025,7 +3027,7 @@ static void HandleKeyboard(const char *k) {
CASE('f', OnFinish());
CASE('c', OnContinueTui());
CASE('C', displayexec = false; OnContinueExec());
CASE('D', displayexec = true; OnContinueExec());
CASE('D', displayexec = true; OnContinueExec());
CASE('R', OnRestart());
CASE('x', OnXmmDisp());
CASE('t', OnXmmType());
Expand Down Expand Up @@ -3571,12 +3573,12 @@ int VirtualMachine(int argc, char *argv[]) {
do {
action = 0;
ptyisenabled = false;
vidya = m->metal? 3: kModePty;
vidya = m->metal ? 3 : kModePty;
if (vidya != kModePty) {
VidyaServiceSetMode(vidya);
}
LoadProgram(m, codepath, codepath,
argv + optind_ - 1 + FLAG_zero, environ, FLAG_bios);
LoadProgram(m, codepath, codepath, argv + optind_ - 1 + FLAG_zero, environ,
FLAG_bios);
if (m->system->codesize) {
ophits = (unsigned long *)AllocateBig(
m->system->codesize * sizeof(unsigned long), PROT_READ | PROT_WRITE,
Expand Down
90 changes: 7 additions & 83 deletions blink/checked.h
Original file line number Diff line number Diff line change
@@ -1,90 +1,14 @@
#ifndef BLINK_CHECKED_H_
#define BLINK_CHECKED_H_
#ifndef EASYCKDINT_H_
#define EASYCKDINT_H_
#if defined(__has_include) && __has_include(<stdckdint.h>)
#include <stdckdint.h>
#elif defined(NDEBUG) && \
((defined(__GNUC__) && __GNUC__ >= 5 && !defined(__ICC)) || \
(defined(__has_builtin) && (__has_builtin(__builtin_add_overflow) && \
__has_builtin(__builtin_sub_overflow) && \
__has_builtin(__builtin_mul_overflow))))
#else

#define __STDC_VERSION_STDCKDINT_H__ 202311L

#define ckd_add(res, x, y) __builtin_add_overflow((x), (y), (res))
#define ckd_sub(res, x, y) __builtin_sub_overflow((x), (y), (res))
#define ckd_mul(res, x, y) __builtin_mul_overflow((x), (y), (res))

#else
#include <limits.h>
#include <stdint.h>

#define ckd_add(res, x, y) __ckd_arithmetic(add, res, x, y)
#define ckd_sub(res, x, y) __ckd_arithmetic(sub, res, x, y)
#define ckd_mul(res, x, y) __ckd_arithmetic(mul, res, x, y)

#define __ckd_arithmetic(op, res, x, y) \
(sizeof(*(res)) == sizeof(int) ? __ckd_##op((int *)(res), x, y) \
: sizeof(*(res)) == sizeof(long long) \
? __ckd_##op##ll((long long *)(res), x, y) \
: __ckd_trap())

#define __ckd_mul_overflow(x, y, min, max) \
if (x > 0) { \
if (y > 0) { \
if (x > max / y) { \
return 1; \
} \
} else { \
if (y < min / x) { \
return 1; \
} \
} \
} else { \
if (y > 0) { \
if (x < min / y) { \
return 1; \
} \
} else { \
if (x && y < max / x) { \
return 1; \
} \
} \
} \
return 0

static inline int __ckd_trap(void) {
volatile int __x = 0;
return 1 / __x;
}

static inline int __ckd_add(int *__z, int __x, int __y) {
unsigned int __a, __b, __c;
*__z = __c = (__a = __x) + (__b = __y);
return ((__c ^ __a) & (__c ^ __b)) >> (sizeof(int) * CHAR_BIT - 1);
}
static inline int __ckd_addll(long long *__z, long long __x, long long __y) {
unsigned long long __a, __b, __c;
*__z = __c = (__a = __x) + (__b = __y);
return ((__c ^ __a) & (__c ^ __b)) >> (sizeof(long long) * CHAR_BIT - 1);
}

static inline int __ckd_sub(int *__z, int __x, int __y) {
unsigned int __a, __b, __c;
*__z = __c = (__a = __x) - (__b = __y);
return ((__a ^ __b) & (__c ^ __a)) >> (sizeof(int) * CHAR_BIT - 1);
}
static inline int __ckd_subll(long long *__z, long long __x, long long __y) {
unsigned long long __a, __b, __c;
*__z = __c = (__a = __x) - (__b = __y);
return ((__a ^ __b) & (__c ^ __a)) >> (sizeof(long long) * CHAR_BIT - 1);
}

static inline int __ckd_mul(int *__z, int __x, int __y) {
*__z = (unsigned)__x * (unsigned)__y;
__ckd_mul_overflow(__x, __y, INT_MIN, INT_MAX);
}
static inline int __ckd_mulll(long long *__z, long long __x, long long __y) {
*__z = (unsigned long long)__x * (unsigned long long)__y;
__ckd_mul_overflow(__x, __y, LLONG_MIN, LLONG_MAX);
}

#endif
#endif /* BLINK_CHECKED_H_ */
#endif /* <stdckdint.h> */
#endif /* EASYCKDINT_H_ */
2 changes: 1 addition & 1 deletion blink/diself.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ static void DisLoadElfLoads(struct Dis *d, Elf64_Ehdr_ *ehdr, size_t esize,
long i;
Elf64_Phdr_ *phdr;
for (i = 0; i < Read16(ehdr->phnum); ++i) {
phdr = GetElfSegmentHeaderAddress(ehdr, esize, i);
phdr = GetElfProgramHeaderAddress(ehdr, esize, i);
if (Read32(phdr->type) != PT_LOAD_) continue;
if (d->loads.i == d->loads.n) {
d->loads.n += 2;
Expand Down
62 changes: 30 additions & 32 deletions blink/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ i64 GetElfMemorySize(const Elf64_Ehdr_ *ehdr, size_t size, i64 *base) {
phdr = (const Elf64_Phdr_ *)((const u8 *)ehdr + off);
if (Read32(phdr->type) == PT_LOAD_) {
x = Read64(phdr->vaddr);
if (ckd_add(&y, x, Read64(phdr->memsz))) return -1;
if (ckd_add(&y, x, (i64)Read64(phdr->memsz))) return -1;
lo = MIN(x, lo);
hi = MAX(y, hi);
}
Expand All @@ -62,7 +62,7 @@ char *GetElfString(const Elf64_Ehdr_ *elf, // validated
size_t mapsize, // validated
const char *strtab, // validated
size_t rva) { // foreign
int64_t addr;
uint64_t addr;
if (!strtab) return 0;
if (ckd_add(&addr, (uintptr_t)strtab, rva)) return 0;
if (addr >= (uintptr_t)elf + mapsize) return 0;
Expand All @@ -73,35 +73,46 @@ char *GetElfString(const Elf64_Ehdr_ *elf, // validated
return (char *)(uintptr_t)addr;
}

Elf64_Phdr_ *GetElfSegmentHeaderAddress(const Elf64_Ehdr_ *elf, //
Elf64_Phdr_ *GetElfProgramHeaderAddress(const Elf64_Ehdr_ *elf, //
size_t mapsize, //
u16 i) { //
int64_t last, addr;
uint64_t off;
if (i >= Read16(elf->phnum)) return 0;
if (ckd_add(&addr, (uintptr_t)elf, Read64(elf->phoff))) return 0;
if (ckd_add(&addr, addr, (u32)i * Read16(elf->phentsize))) return 0;
if (ckd_add(&last, addr, Read16(elf->phentsize))) return 0;
if (last > (uintptr_t)elf + mapsize) return 0;
if (addr != (uintptr_t)addr) return 0;
return (Elf64_Phdr_ *)(uintptr_t)addr;
if (Read64(elf->phoff) <= 0) return 0;
if (Read64(elf->phoff) >= mapsize) return 0;
if (Read16(elf->phentsize) < sizeof(Elf64_Phdr_)) return 0;
off = Read64(elf->phoff) + (unsigned)i * Read16(elf->phentsize);
if (off > mapsize) return 0;
return (Elf64_Phdr_ *)((char *)elf + off);
}

Elf64_Shdr_ *GetElfSectionHeaderAddress(const Elf64_Ehdr_ *elf, //
size_t mapsize, //
u16 i) { //
uint64_t off;
if (i >= Read16(elf->shnum)) return 0;
if (Read64(elf->shoff) <= 0) return 0;
if (Read64(elf->shoff) >= mapsize) return 0;
if (Read16(elf->shentsize) < sizeof(Elf64_Shdr_)) return 0;
off = Read64(elf->shoff) + (unsigned)i * Read16(elf->shentsize);
if (off > mapsize) return 0;
return (Elf64_Shdr_ *)((char *)elf + off);
}

// note: should not be used on bss section
void *GetElfSectionAddress(const Elf64_Ehdr_ *elf, // validated
size_t mapsize, // validated
const Elf64_Shdr_ *shdr) { // foreign
int64_t addr, last;
uint64_t last;
if (!shdr) return 0;
if (ckd_add(&addr, (uintptr_t)elf, Read64(shdr->offset))) return 0;
if (ckd_add(&last, addr, Read64(shdr->size))) return 0;
if (last > (uintptr_t)elf + mapsize) return 0;
if (addr != (uintptr_t)addr) return 0;
return (void *)(uintptr_t)addr;
if (!Read64(shdr->size)) return 0;
if (ckd_add(&last, Read64(shdr->offset), Read64(shdr->size))) return 0;
if (last > mapsize) return 0;
return (char *)elf + Read64(shdr->offset);
}

char *GetElfSectionNameStringTable(const Elf64_Ehdr_ *elf, //
size_t mapsize) { //
if (!Read64(elf->shoff) || !Read16(elf->shentsize)) return 0;
return (char *)GetElfSectionAddress(
elf, mapsize,
GetElfSectionHeaderAddress(elf, mapsize, Read16(elf->shstrndx)));
Expand All @@ -115,19 +126,6 @@ const char *GetElfSectionName(const Elf64_Ehdr_ *elf, //
Read32(shdr->name));
}

Elf64_Shdr_ *GetElfSectionHeaderAddress(const Elf64_Ehdr_ *elf, //
size_t mapsize, //
u16 i) { //
int64_t addr, last;
if (i >= Read16(elf->shnum)) return 0;
if (ckd_add(&addr, (uintptr_t)elf, Read64(elf->shoff))) return 0;
if (ckd_add(&addr, addr, (u32)i * Read16(elf->shentsize))) return 0;
if (ckd_add(&last, addr, Read16(elf->shentsize))) return 0;
if (last > (uintptr_t)elf + mapsize) return 0;
if (addr != (uintptr_t)addr) return 0;
return (Elf64_Shdr_ *)(uintptr_t)addr;
}

static char *GetElfStringTableImpl(const Elf64_Ehdr_ *elf, //
size_t mapsize, //
const char *kind) { //
Expand Down Expand Up @@ -160,10 +158,10 @@ static Elf64_Sym_ *GetElfSymbolTableImpl(const Elf64_Ehdr_ *elf, //
Elf64_Shdr_ *shdr;
for (i = Read16(elf->shnum); i > 0; --i) {
if ((shdr = GetElfSectionHeaderAddress(elf, mapsize, i - 1)) &&
Read64(shdr->entsize) == sizeof(Elf64_Sym_) &&
Read32(shdr->type) == kind) {
if (Read64(shdr->entsize) != sizeof(Elf64_Sym_)) continue;
if (out_count) {
*out_count = Read64(shdr->size) / Read64(shdr->entsize);
*out_count = Read64(shdr->size) / sizeof(Elf64_Sym_);
}
return (Elf64_Sym_ *)GetElfSectionAddress(elf, mapsize, shdr);
}
Expand Down
10 changes: 5 additions & 5 deletions blink/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -421,18 +421,18 @@
#define DF_P1_LAZYLOAD_ 0x00000001
#define DF_P1_GROUPPERM_ 0x00000002

#define ELF64_ST_BIND_(val) (((unsigned char)(val)) >> 4)
#define ELF64_ST_BIND_(val) (((u8)(val)) >> 4)
#define ELF64_ST_TYPE_(val) ((val)&0xf)
#define ELF64_ST_INFO_(bind, type) (((bind) << 4) + ((type)&0xf))
#define ELF64_ST_VISIBILITY_(o) ((o)&0x03)

#define ELF64_R_SYM_(i) ((i) >> 32)
#define ELF64_R_TYPE_(i) ((i)&0xffffffff)
#define ELF64_R_INFO_(sym, type) ((((Elf64_Xword)(sym)) << 32) + (type))
#define ELF64_R_INFO_(sym, type) ((((u64)(sym)) << 32) + (type))

#define ELF64_M_SYM_(info) ((info) >> 8)
#define ELF64_M_SIZE_(info) ((unsigned char)(info))
#define ELF64_M_INFO_(sym, size) (((sym) << 8) + (unsigned char)(size))
#define ELF64_M_SIZE_(info) ((u8)(info))
#define ELF64_M_INFO_(sym, size) (((sym) << 8) + (u8)(size))

#define NT_PRSTATUS_ 1
#define NT_PRFPREG_ 2
Expand Down Expand Up @@ -620,7 +620,7 @@ typedef struct Elf64_Nhdr_ {
u8 type[4]; // u32
} Elf64_Nhdr_;

Elf64_Phdr_ *GetElfSegmentHeaderAddress(const Elf64_Ehdr_ *, size_t, u16);
Elf64_Phdr_ *GetElfProgramHeaderAddress(const Elf64_Ehdr_ *, size_t, u16);
char *GetElfStringTable(const Elf64_Ehdr_ *, size_t);
Elf64_Shdr_ *GetElfSectionHeaderAddress(const Elf64_Ehdr_ *, size_t, u16);
const char *GetElfSectionName(const Elf64_Ehdr_ *, size_t, Elf64_Shdr_ *);
Expand Down
2 changes: 1 addition & 1 deletion blink/jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1756,7 +1756,7 @@ bool AlignJit(struct JitBlock *jb, int align, int misalign) {
unassert(misalign >= 0 && misalign < align);
while ((jb->index & (align - 1)) != misalign) {
#ifdef __x86_64__
// Intel's Official Fat NOP Instructions
// Intel's Official Multibyte NOP Instructions
//
// 90 nop
// 6690 xchg %ax,%ax
Expand Down
2 changes: 1 addition & 1 deletion blink/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ static bool LoadElf(struct Machine *m, //
&elf->at_base);
m->ip = elf->at_base + Read64(ehdri->entry);
for (prot = i = 0; i < Read16(ehdri->phnum); ++i) {
phdr = GetElfSegmentHeaderAddress(ehdri, st.st_size, i);
phdr = GetElfProgramHeaderAddress(ehdri, st.st_size, i);
switch (Read32(phdr->type)) {
case PT_LOAD_:
end = LoadElfLoadSegment(m, elf->interpreter, ehdri, st.st_size, phdr,
Expand Down
Loading

0 comments on commit 768e9bb

Please sign in to comment.