1 //-----------------------------------------------------------------------------
2 // Borrowed initially from https://github.com/LuaDist/lpack/blob/master/lpack.c
3 // Copyright (C) 2007 Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br>
4 // Copyright (C) Ignacio Castao <castanyo@yahoo.es>
5 // Copyright (C) Roberto Ierusalimschy <roberto@inf.puc-rio.br>
6 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // See LICENSE.txt for the text of the license.
19 //-----------------------------------------------------------------------------
20 // a Lua library for packing and unpacking binary data
21 //-----------------------------------------------------------------------------
23 #define OP_ZSTRING 'z' /* zero-terminated string */
24 #define OP_BSTRING 'p' /* string preceded by length byte */
25 #define OP_WSTRING 'P' /* string preceded by length word */
26 #define OP_SSTRING 'a' /* string preceded by length size_t */
27 #define OP_STRING 'A' /* string */
28 #define OP_FLOAT 'f' /* float */
29 #define OP_DOUBLE 'd' /* double */
30 #define OP_NUMBER 'n' /* Lua number */
31 #define OP_CHAR 'c' /* char (1-byte int) */
32 #define OP_BYTE 'C' /* byte = unsigned char (1-byte unsigned int) */
33 #define OP_SHORT 's' /* short (2-byte int) */
34 #define OP_USHORT 'S' /* unsigned short (2-byte unsigned int) */
35 #define OP_INT 'i' /* int (4-byte int) */
36 #define OP_UINT 'I' /* unsigned int (4-byte unsigned int) */
37 #define OP_LONG 'l' /* long (8-byte int) */
38 #define OP_ULONG 'L' /* unsigned long (8-byte unsigned int) */
39 #define OP_LITTLEENDIAN '<' /* little endian */
40 #define OP_BIGENDIAN '>' /* big endian */
41 #define OP_NATIVE '=' /* native endian */
51 #include "pm3_binlib.h"
54 static void badcode(lua_State
*L
, int c
) {
55 char s
[] = "bad code `?'";
57 luaL_argerror(L
, 1, s
);
60 static int doendian(int c
) {
63 if (c
== OP_LITTLEENDIAN
) return !e
;
64 if (c
== OP_BIGENDIAN
) return e
;
65 if (c
== OP_NATIVE
) return 0;
69 static void doswap(int swap
, void *p
, size_t n
) {
73 for (i
= 0, j
= n
- 1, n
= n
/ 2; n
--; i
++, j
--) {
81 #define UNPACKNUMBER(OP,T) \
86 if (i+m>len) { done = 1; break;} \
90 lua_pushnumber(L,(lua_Number)a); \
95 #define UNPACKSTRING(OP,T) \
100 if (i + m > len) { done = 1; break; } \
101 memcpy(&l, s+i, m); \
103 if (i + m + l > len) { done = 1; break;} \
105 lua_pushlstring(L,s+i,l); \
111 #define HEXDIGITS(DIG) \
112 "0123456789ABCDEF"[DIG]
114 static int l_unpack(lua_State
*L
) { /** unpack(f,s, [init]) */
116 const char *s
= luaL_checklstring(L
, 2, &len
); /* switched s and f */
117 const char *f
= luaL_checkstring(L
, 1);
118 int i_read
= luaL_optinteger(L
, 3, 1) - 1;
119 //int i_read = (int)luaL_optint(L,(3),(1))-1;
130 while (*f
&& done
== 0) {
133 if (isdigit((int)(unsigned char) *f
)) {
135 while (isdigit((int)(unsigned char) *f
)) N
= 10 * N
+ (*f
++) - '0';
136 if (N
== 0 && c
== OP_STRING
) { lua_pushliteral(L
, ""); ++n
; }
138 while (N
-- && done
== 0) switch (c
) {
139 case OP_LITTLEENDIAN
:
148 if (i
+ N
> len
) {done
= 1; break; }
149 lua_pushlstring(L
, s
+ i
, N
);
157 if (i
>= len
) {done
= 1; break; }
159 lua_pushlstring(L
, s
+ i
, l
);
165 UNPACKSTRING(OP_BSTRING
, uint8_t)
166 UNPACKSTRING(OP_WSTRING
, uint16_t)
167 UNPACKSTRING(OP_SSTRING
, uint32_t)
168 UNPACKNUMBER(OP_NUMBER
, lua_Number
)
169 UNPACKNUMBER(OP_DOUBLE
, double)
170 UNPACKNUMBER(OP_FLOAT
, float)
171 UNPACKNUMBER(OP_CHAR
, int8_t)
172 UNPACKNUMBER(OP_BYTE
, uint8_t)
173 UNPACKNUMBER(OP_SHORT
, int16_t)
174 UNPACKNUMBER(OP_USHORT
, uint16_t)
175 UNPACKNUMBER(OP_INT
, int32_t)
176 UNPACKNUMBER(OP_UINT
, uint32_t)
177 UNPACKNUMBER(OP_LONG
, int64_t)
178 UNPACKNUMBER(OP_ULONG
, uint64_t)
182 luaL_buffinit(L
, &buf
);
184 if (i
+ N
> len
) {done
= 1; break;}
185 for (unsigned int ii
= i
; ii
< i
+ N
; ii
++) {
186 int val
= s
[ii
] & 0xF0;
188 hdigit
= HEXDIGITS(val
);
189 luaL_addlstring(&buf
, &hdigit
, 1);
192 hdigit
= HEXDIGITS(val
);
193 luaL_addlstring(&buf
, &hdigit
, 1);
195 luaL_pushresult(&buf
);
210 lua_pushnumber(L
, i
+ 1);
211 lua_replace(L
, -n
- 2);
215 #define PACKNUMBER(OP,T) \
218 lua_Number n = luaL_checknumber(L,i++); \
220 doswap(swap,&a,sizeof(a)); \
221 luaL_addlstring(&b,(char*)&a,sizeof(a)); \
225 #define PACKSTRING(OP,T) \
229 const char *a=luaL_checklstring(L,i++,&l); \
231 doswap(swap,&ll,sizeof(ll)); \
232 luaL_addlstring(&b,(char*)&ll,sizeof(ll)); \
233 luaL_addlstring(&b,a,l); \
237 static int l_pack(lua_State
*L
) { /** pack(f,...) */
239 const char *f
= luaL_checkstring(L
, 1);
242 luaL_buffinit(L
, &b
);
246 if (isdigit((int)(unsigned char) *f
)) {
248 while (isdigit((int)(unsigned char) *f
)) N
= 10 * N
+ (*f
++) - '0';
250 while (N
--) switch (c
) {
251 case OP_LITTLEENDIAN
:
261 const char *a
= luaL_checklstring(L
, i
++, &l
);
262 luaL_addlstring(&b
, a
, l
+ (c
== OP_ZSTRING
));
265 PACKSTRING(OP_BSTRING
, uint8_t)
266 PACKSTRING(OP_WSTRING
, uint16_t)
267 PACKSTRING(OP_SSTRING
, uint32_t)
268 PACKNUMBER(OP_NUMBER
, lua_Number
)
269 PACKNUMBER(OP_DOUBLE
, double)
270 PACKNUMBER(OP_FLOAT
, float)
271 PACKNUMBER(OP_CHAR
, int8_t)
272 PACKNUMBER(OP_BYTE
, uint8_t)
273 PACKNUMBER(OP_SHORT
, int16_t)
274 PACKNUMBER(OP_USHORT
, uint16_t)
275 PACKNUMBER(OP_INT
, int32_t)
276 PACKNUMBER(OP_UINT
, uint32_t)
277 PACKNUMBER(OP_LONG
, int64_t)
278 PACKNUMBER(OP_ULONG
, uint64_t)
280 // doing digit parsing the lpack way
281 unsigned char sbyte
= 0;
285 const char *a
= luaL_checklstring(L
, i
++, &l
);
286 for (ii
= 0; ii
< l
; ii
++) {
287 if (isxdigit((int)(unsigned char) a
[ii
])) {
288 if (isdigit((int)(unsigned char) a
[ii
])) {
289 sbyte
+= a
[ii
] - '0';
291 } else if (a
[ii
] >= 'A' && a
[ii
] <= 'F') {
292 sbyte
+= a
[ii
] - 'A' + 10;
294 } else if (a
[ii
] >= 'a' && a
[ii
] <= 'f') {
295 sbyte
+= a
[ii
] - 'a' + 10;
300 } else if (odd
== 2) {
301 luaL_addlstring(&b
, (char *) &sbyte
, 1);
305 } else if (isspace(a
[ii
])) {
308 /* err ... ignore too*/
312 luaL_addlstring(&b
, (char *) &sbyte
, 1);
328 static const luaL_Reg binlib
[] = {
330 {"unpack", l_unpack
},
334 LUALIB_API
int luaopen_binlib(lua_State
*L
);
335 LUALIB_API
int luaopen_binlib(lua_State
*L
) {
336 luaL_newlib(L
, binlib
);
342 int set_bin_library(lua_State
*L
) {
344 luaL_requiref(L
, "bin", luaopen_binlib
, 1);