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 hidden or 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 hidden or 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