Created
October 28, 2010 04:01
-
-
Save droyo/650612 to your computer and use it in GitHub Desktop.
Binary regexp parser for cifsd by cinap_lenrek
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some usage of the parser: | |
EXAMPLES | |
smb.c:803: if(!unpack(h, p, e, "#0b{*2}#1w{}")){ | |
smb.c:827: if(!unpack(h, p, e, "#0b{*2}#1w{_f}", r->o->nameunpack, &name)){ | |
smb.c:861: if(!unpack(h, p, e, "#0b{*2wl__________}#1w{_f}", &attr, &mtime, r->o->nameunpack, &name)){ | |
smb.c:907: if(!unpack(h, p, e, "#0b{*2}#1w{_f}", r->o->nameunpack, &name)){ | |
smb.c:945: if(!unpack(h, p, e, "#0b{*2w}#1w{}", &fid)){ | |
smb.c:978: if(!unpack(h, p, e, "#0b{*2}#1w{}")){ | |
smb.c:1101: if(!unpack(t->in.param.b, t->in.param.p, t->in.param.e, "w____f", | |
smb.c:1102: &level, t->r->o->nameunpack, &name)){ | |
smb.c:1137: if(!unpack(t->in.param.b, t->in.param.p, t->in.param.e, "ww", &fid, &level)){ | |
smb.c:1173: if(!unpack(b, p, e, "____wwww__________", &adt, &atm, &mdt, &mtm)) | |
smb.c:1180: if(f == nil || !unpack(b, p, e, "________vv________l____", &atime, &mtime, &attr)) | |
smb.c:1196: if(f == nil || !unpack(b, p, e, "b", &delete)) | |
smb.c:1205: if(f == nil || !unpack(b, p, e, "v", &len)) | |
smb.c:1237: if(!unpack(t->in.param.b, t->in.param.p, t->in.param.e, "w____f", &level, | |
smb.c:1238: t->r->o->nameunpack, &name)){ | |
smb.c:1271: if(!unpack(t->in.param.b, t->in.param.p, t->in.param.e, "ww__", &fid, &level)){ | |
smb.c:1308: if(!unpack(t->in.param.b, t->in.param.p, t->in.param.e, "w", &level)){ | |
smb.c:1390: if(!unpack(t->in.param.b, t->in.param.p, t->in.param.e, "wwww____f", | |
smb.c:1391: &attr, &count, &flags, &level, t->r->o->nameunpack, &name)){ | |
smb.c:1457: if(!unpack(t->in.param.b, t->in.param.p, t->in.param.e, "wwwlwf", | |
smb.c:1458: &sid, &count, &level, &index, &flags, t->r->o->nameunpack, &name)){ | |
smb.c:1559: if(!unpack(h, p, e, "#0b{*2wwwwb_w______#3w@3w#4w@4w#1b_[*2]}#2w{[?][?]}", | |
smb.c:1565: unpack(sa, sa, se, "w", &t.cmd); | |
util.c:222: strunpack8(uchar *, uchar *p, uchar *e, char **dp, int term, Rune (*tr)(Rune)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <u.h> | |
#include <libc.h> | |
#include "dat.h" | |
#include "fns.h" | |
/* See | |
* http://9fans.net/archive/2010/09/288 | |
* for details. This is not my code. | |
*/ | |
int | |
unpack(uchar *b, uchar *p, uchar *e, char *f, ...) | |
{ | |
va_list a; | |
int r; | |
va_start(a, f); | |
r = vunpack(b, p, e, f, a); | |
va_end(a); | |
return r; | |
} | |
int | |
pack(uchar *b, uchar *p, uchar *e, char *f, ...) | |
{ | |
va_list a; | |
int r; | |
va_start(a, f); | |
r = vpack(b, p, e, f, a); | |
va_end(a); | |
return r; | |
} | |
int | |
vunpack(uchar *b, uchar *p, uchar *e, char *f, va_list a) | |
{ | |
struct { | |
void *prev; | |
int o, c, i; | |
uchar *e; | |
uchar **ap, **ae; | |
} sub[8], *sp, *sa; | |
int (*funpack)(uchar *, uchar *, uchar *, void *); | |
char c, ff[2]; | |
int i, x, n; | |
uchar *t; | |
memset(sub, 0, sizeof(sub)); | |
for(sp = sub; sp < sub+nelem(sub); sp++){ | |
sp->o = -1; | |
sp->c = -1; | |
sp->i = 1; | |
} | |
t = p; | |
sp = nil; | |
sa = sub; | |
while(c = *f++){ | |
switch(c){ | |
case '_': | |
if(p >= e) | |
return 0; | |
p++; | |
break; | |
case 'b': | |
if(p >= e) | |
return 0; | |
*va_arg(a, int*) = *p++; | |
break; | |
case 'w': | |
if(p+1 >= e) | |
return 0; | |
*va_arg(a, int*) = (int)p[1]<<8 | (int)p[0]; | |
p+=2; | |
break; | |
case 'l': | |
if(p+3 >= e) | |
return 0; | |
*va_arg(a, int*) = (int)p[3]<<24 | (int)p[2]<<16 | (int)p[1]<<8 | (int)p[0]; | |
p+=4; | |
break; | |
case 'v': | |
if(p+7 >= e) | |
return 0; | |
*va_arg(a, vlong*) = | |
(vlong)p[7]<<56 | | |
(vlong)p[6]<<48 | | |
(vlong)p[5]<<40 | | |
(vlong)p[4]<<32 | | |
(vlong)p[3]<<24 | | |
(vlong)p[2]<<16 | | |
(vlong)p[1]<<8 | | |
(vlong)p[0]; | |
p += 8; | |
break; | |
case '%': | |
x = *f++ - '0'; | |
while((p - b) % x) | |
p++; | |
break; | |
case 'f': | |
funpack = va_arg(a, void*); | |
if((n = funpack(b, p, e, va_arg(a, void*))) == 0) | |
return 0; | |
p += n; | |
break; | |
case '#': | |
case '@': | |
x = *f++ - '0'; | |
ff[0] = *f++; | |
ff[1] = 0; | |
if((n = unpack(b, p, e, ff, &i)) == 0) | |
return 0; | |
p += n; | |
if(c == '#'){ | |
sub[x].c = i; | |
} else { | |
sub[x].o = i; | |
} | |
break; | |
case '{': | |
case '[': | |
sa->prev = sp; | |
sp = sa++; | |
if(*f == '*'){ | |
sp->i = f[1]-'0'; | |
f += 2; | |
} | |
if(sp->o >= 0 && b + sp->o > p) | |
if(b + sp->o <= e || *f != '?') | |
p = b + sp->o; | |
if(*f == '?') | |
f++; | |
sp->o = p - b; | |
sp->e = e; | |
if(sp->c >= 0){ | |
e = p + sp->c * sp->i; | |
if(e > sp->e) | |
return 0; | |
} | |
if(c == '['){ | |
sp->ap = va_arg(a, uchar**); | |
sp->ae = va_arg(a, uchar**); | |
} | |
break; | |
case '}': | |
case ']': | |
e = sp->e; | |
if(sp->c < 0) | |
sp->c = ((p - (b + sp->o))+sp->i-1)/sp->i; | |
p = b + sp->o + sp->c * sp->i; | |
if(p > e) | |
return 0; | |
if(sp->ap) | |
*sp->ap = b + sp->o; | |
if(sp->ae) | |
*sp->ae = p; | |
sp = sp->prev; | |
break; | |
case '.': | |
*va_arg(a, uchar**) = p; | |
break; | |
} | |
if(p > e) | |
return 0; | |
} | |
return p - t; | |
} | |
vpack(uchar *b, uchar *p, uchar *e, char *f, va_list a) | |
{ | |
struct { | |
void *prev; | |
int o, i; | |
uchar *wc, *wo, wcf, wof; | |
} sub[8], *sp, *sa; | |
int (*fpack)(uchar *, uchar *, uchar *, void *); | |
char c, ff[2]; | |
int i, x, n; | |
vlong v; | |
uchar *t; | |
memset(sub, 0, sizeof(sub)); | |
for(sp = sub; sp < sub+nelem(sub); sp++){ | |
sp->o = -1; | |
sp->i = 1; | |
} | |
t = p; | |
sp = nil; | |
sa = sub; | |
while(c = *f++){ | |
switch(c){ | |
case '_': | |
if(p >= e) | |
return 0; | |
*p++ = 0; | |
break; | |
case 'b': | |
if(p >= e) | |
return 0; | |
*p++ = va_arg(a, int); | |
break; | |
case 'w': | |
if(p+1 >= e) | |
return 0; | |
i = va_arg(a, int); | |
*p++ = i & 0xFF; | |
*p++ = i>>8 & 0xFF; | |
break; | |
case 'l': | |
if(p+3 >= e) | |
return 0; | |
i = va_arg(a, int); | |
*p++ = i & 0xFF; | |
*p++ = i>>8 & 0xFF; | |
*p++ = i>>16 & 0xFF; | |
*p++ = i>>24 & 0xFF; | |
break; | |
case 'v': | |
if(p+7 >= e) | |
return 0; | |
v = va_arg(a, vlong); | |
*p++ = v & 0xFF; | |
*p++ = v>>8 & 0xFF; | |
*p++ = v>>16 & 0xFF; | |
*p++ = v>>24 & 0xFF; | |
*p++ = v>>32 & 0xFF; | |
*p++ = v>>40 & 0xFF; | |
*p++ = v>>48 & 0xFF; | |
*p++ = v>>56 & 0xFF; | |
break; | |
case '%': | |
x = *f++ - '0'; | |
while((p - b) % x){ | |
if(p >= e) | |
return 0; | |
*p++ = 0; | |
} | |
break; | |
case 'f': | |
fpack = va_arg(a, void*); | |
if((n = fpack(b, p, e, va_arg(a, void*))) == 0) | |
return 0; | |
p += n; | |
break; | |
case '#': | |
case '@': | |
x = *f++ - '0'; | |
ff[0] = *f++; | |
ff[1] = 0; | |
if((n = pack(b, p, e, ff, 0)) == 0) | |
return 0; | |
if(c == '#'){ | |
sub[x].wc = p; | |
sub[x].wcf = ff[0]; | |
} else { | |
sub[x].wo = p; | |
sub[x].wof = ff[0]; | |
} | |
p += n; | |
break; | |
case '{': | |
case '[': | |
sa->prev = sp; | |
sp = sa++; | |
if(*f == '*'){ | |
sp->i = f[1]-'0'; | |
f += 2; | |
} | |
if(*f == '?') | |
f++; | |
sp->o = p - b; | |
if(c == '['){ | |
uchar *s, *se; | |
s = va_arg(a, uchar*); | |
se = va_arg(a, uchar*); | |
n = se - s; | |
if(n < 0 || p + n > e) | |
return 0; | |
if(p != s) | |
memmove(p, s, n); | |
p += n; | |
} | |
break; | |
case '}': | |
case ']': | |
n = ((p - (b + sp->o))+sp->i-1)/sp->i; | |
p = b + sp->o + n * sp->i; | |
if(sp->wc){ | |
ff[0] = sp->wcf; | |
ff[1] = 0; | |
pack(b, sp->wc, e, ff, n); | |
} | |
if(sp->wo){ | |
ff[0] = sp->wof; | |
ff[1] = 0; | |
pack(b, sp->wo, e, ff, sp->o); | |
} | |
sp = sp->prev; | |
break; | |
case '.': | |
*va_arg(a, uchar**) = p; | |
break; | |
} | |
if(p > e) | |
return 0; | |
} | |
return p - t; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment