Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
L
libplist
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
pwn
libplist
Commits
40cf910a
Commit
40cf910a
authored
Feb 05, 2015
by
Nikias Bassen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bplist: Refactor binary plist parsing in a recursive way
parent
6a781e6f
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
167 additions
and
209 deletions
+167
-209
bplist.c
src/bplist.c
+167
-209
No files found.
src/bplist.c
View file @
40cf910a
/*
/*
* plist.c
*
b
plist.c
* Binary plist implementation
* Binary plist implementation
*
*
* Copyright (c) 2008 Jonathan Beck All Rights Reserved.
* Copyright (c) 2011-2015 Nikias Bassen, All Rights Reserved.
* Copyright (c) 2008-2010 Jonathan Beck, All Rights Reserved.
*
*
* This library is free software; you can redistribute it and/or
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* modify it under the terms of the GNU Lesser General Public
...
@@ -95,7 +96,7 @@ static void float_byte_convert(uint8_t * address, size_t size)
...
@@ -95,7 +96,7 @@ static void float_byte_convert(uint8_t * address, size_t size)
union
plist_uint_ptr
union
plist_uint_ptr
{
{
void
*
src
;
const
void
*
src
;
uint8_t
*
u8ptr
;
uint8_t
*
u8ptr
;
uint16_t
*
u16ptr
;
uint16_t
*
u16ptr
;
uint32_t
*
u32ptr
;
uint32_t
*
u32ptr
;
...
@@ -202,7 +203,20 @@ static uint32_t uint24_from_be(union plist_uint_ptr buf)
...
@@ -202,7 +203,20 @@ static uint32_t uint24_from_be(union plist_uint_ptr buf)
#define NODE_IS_ROOT(x) (((node_t*)x)->isRoot)
#define NODE_IS_ROOT(x) (((node_t*)x)->isRoot)
static
plist_t
parse_uint_node
(
char
*
bnode
,
uint8_t
size
,
char
**
next_object
)
struct
bplist_data
{
const
char
*
data
;
uint64_t
size
;
uint64_t
num_objects
;
uint8_t
dict_size
;
uint8_t
offset_size
;
const
char
*
offset_table
;
uint32_t
level
;
uint32_t
*
used_indexes
;
};
static
plist_t
parse_bin_node_at_index
(
struct
bplist_data
*
bplist
,
uint32_t
node_index
);
static
plist_t
parse_uint_node
(
const
char
**
bnode
,
uint8_t
size
)
{
{
plist_data_t
data
=
plist_new_plist_data
();
plist_data_t
data
=
plist_new_plist_data
();
...
@@ -213,12 +227,12 @@ static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object)
...
@@ -213,12 +227,12 @@ static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object)
case
sizeof
(
uint16_t
):
case
sizeof
(
uint16_t
):
case
sizeof
(
uint32_t
):
case
sizeof
(
uint32_t
):
case
sizeof
(
uint64_t
):
case
sizeof
(
uint64_t
):
memcpy
(
&
data
->
intval
,
bnode
,
size
);
memcpy
(
&
data
->
intval
,
*
bnode
,
size
);
data
->
intval
=
UINT_TO_HOST
(
&
data
->
intval
,
size
);
data
->
intval
=
UINT_TO_HOST
(
&
data
->
intval
,
size
);
data
->
length
=
sizeof
(
uint64_t
);
data
->
length
=
sizeof
(
uint64_t
);
break
;
break
;
case
16
:
case
16
:
memcpy
(
&
data
->
intval
,
bnode
+
8
,
sizeof
(
uint64_t
));
memcpy
(
&
data
->
intval
,
(
*
bnode
)
+
8
,
sizeof
(
uint64_t
));
data
->
intval
=
UINT_TO_HOST
(
&
data
->
intval
,
sizeof
(
uint64_t
));
data
->
intval
=
UINT_TO_HOST
(
&
data
->
intval
,
sizeof
(
uint64_t
));
data
->
length
=
size
;
data
->
length
=
size
;
break
;
break
;
...
@@ -227,13 +241,13 @@ static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object)
...
@@ -227,13 +241,13 @@ static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object)
return
NULL
;
return
NULL
;
};
};
*
next_object
=
bnode
+
size
;
(
*
bnode
)
+=
size
;
data
->
type
=
PLIST_UINT
;
data
->
type
=
PLIST_UINT
;
return
node_create
(
NULL
,
data
);
return
node_create
(
NULL
,
data
);
}
}
static
plist_t
parse_real_node
(
c
har
*
bnode
,
uint8_t
size
)
static
plist_t
parse_real_node
(
c
onst
char
*
*
bnode
,
uint8_t
size
)
{
{
plist_data_t
data
=
plist_new_plist_data
();
plist_data_t
data
=
plist_new_plist_data
();
float
floatval
=
0
.
0
;
float
floatval
=
0
.
0
;
...
@@ -241,7 +255,7 @@ static plist_t parse_real_node(char *bnode, uint8_t size)
...
@@ -241,7 +255,7 @@ static plist_t parse_real_node(char *bnode, uint8_t size)
size
=
1
<<
size
;
// make length less misleading
size
=
1
<<
size
;
// make length less misleading
buf
=
malloc
(
size
);
buf
=
malloc
(
size
);
memcpy
(
buf
,
bnode
,
size
);
memcpy
(
buf
,
*
bnode
,
size
);
switch
(
size
)
switch
(
size
)
{
{
case
sizeof
(
float
):
case
sizeof
(
float
):
...
@@ -265,7 +279,7 @@ static plist_t parse_real_node(char *bnode, uint8_t size)
...
@@ -265,7 +279,7 @@ static plist_t parse_real_node(char *bnode, uint8_t size)
return
node_create
(
NULL
,
data
);
return
node_create
(
NULL
,
data
);
}
}
static
plist_t
parse_date_node
(
c
har
*
bnode
,
uint8_t
size
)
static
plist_t
parse_date_node
(
c
onst
char
*
*
bnode
,
uint8_t
size
)
{
{
plist_t
node
=
parse_real_node
(
bnode
,
size
);
plist_t
node
=
parse_real_node
(
bnode
,
size
);
plist_data_t
data
=
plist_get_data
(
node
);
plist_data_t
data
=
plist_get_data
(
node
);
...
@@ -279,13 +293,13 @@ static plist_t parse_date_node(char *bnode, uint8_t size)
...
@@ -279,13 +293,13 @@ static plist_t parse_date_node(char *bnode, uint8_t size)
return
node
;
return
node
;
}
}
static
plist_t
parse_string_node
(
c
har
*
bnode
,
uint64_t
size
)
static
plist_t
parse_string_node
(
c
onst
char
*
*
bnode
,
uint64_t
size
)
{
{
plist_data_t
data
=
plist_new_plist_data
();
plist_data_t
data
=
plist_new_plist_data
();
data
->
type
=
PLIST_STRING
;
data
->
type
=
PLIST_STRING
;
data
->
strval
=
(
char
*
)
malloc
(
sizeof
(
char
)
*
(
size
+
1
));
data
->
strval
=
(
char
*
)
malloc
(
sizeof
(
char
)
*
(
size
+
1
));
memcpy
(
data
->
strval
,
bnode
,
size
);
memcpy
(
data
->
strval
,
*
bnode
,
size
);
data
->
strval
[
size
]
=
'\0'
;
data
->
strval
[
size
]
=
'\0'
;
data
->
length
=
strlen
(
data
->
strval
);
data
->
length
=
strlen
(
data
->
strval
);
...
@@ -348,7 +362,7 @@ static char *plist_utf16_to_utf8(uint16_t *unistr, long len, long *items_read, l
...
@@ -348,7 +362,7 @@ static char *plist_utf16_to_utf8(uint16_t *unistr, long len, long *items_read, l
return
outbuf
;
return
outbuf
;
}
}
static
plist_t
parse_unicode_node
(
c
har
*
bnode
,
uint64_t
size
)
static
plist_t
parse_unicode_node
(
c
onst
char
*
*
bnode
,
uint64_t
size
)
{
{
plist_data_t
data
=
plist_new_plist_data
();
plist_data_t
data
=
plist_new_plist_data
();
uint64_t
i
=
0
;
uint64_t
i
=
0
;
...
@@ -359,7 +373,7 @@ static plist_t parse_unicode_node(char *bnode, uint64_t size)
...
@@ -359,7 +373,7 @@ static plist_t parse_unicode_node(char *bnode, uint64_t size)
data
->
type
=
PLIST_STRING
;
data
->
type
=
PLIST_STRING
;
unicodestr
=
(
uint16_t
*
)
malloc
(
sizeof
(
uint16_t
)
*
size
);
unicodestr
=
(
uint16_t
*
)
malloc
(
sizeof
(
uint16_t
)
*
size
);
memcpy
(
unicodestr
,
bnode
,
sizeof
(
uint16_t
)
*
size
);
memcpy
(
unicodestr
,
*
bnode
,
sizeof
(
uint16_t
)
*
size
);
for
(
i
=
0
;
i
<
size
;
i
++
)
for
(
i
=
0
;
i
<
size
;
i
++
)
byte_convert
((
uint8_t
*
)
(
unicodestr
+
i
),
sizeof
(
uint16_t
));
byte_convert
((
uint8_t
*
)
(
unicodestr
+
i
),
sizeof
(
uint16_t
));
...
@@ -375,43 +389,112 @@ static plist_t parse_unicode_node(char *bnode, uint64_t size)
...
@@ -375,43 +389,112 @@ static plist_t parse_unicode_node(char *bnode, uint64_t size)
return
node_create
(
NULL
,
data
);
return
node_create
(
NULL
,
data
);
}
}
static
plist_t
parse_data_node
(
c
har
*
bnode
,
uint64_t
size
)
static
plist_t
parse_data_node
(
c
onst
char
*
*
bnode
,
uint64_t
size
)
{
{
plist_data_t
data
=
plist_new_plist_data
();
plist_data_t
data
=
plist_new_plist_data
();
data
->
type
=
PLIST_DATA
;
data
->
type
=
PLIST_DATA
;
data
->
length
=
size
;
data
->
length
=
size
;
data
->
buff
=
(
uint8_t
*
)
malloc
(
sizeof
(
uint8_t
)
*
size
);
data
->
buff
=
(
uint8_t
*
)
malloc
(
sizeof
(
uint8_t
)
*
size
);
memcpy
(
data
->
buff
,
bnode
,
sizeof
(
uint8_t
)
*
size
);
memcpy
(
data
->
buff
,
*
bnode
,
sizeof
(
uint8_t
)
*
size
);
return
node_create
(
NULL
,
data
);
return
node_create
(
NULL
,
data
);
}
}
static
plist_t
parse_dict_node
(
char
*
bnode
,
uint64_t
size
,
uint32_t
ref_
size
)
static
plist_t
parse_dict_node
(
struct
bplist_data
*
bplist
,
const
char
**
bnode
,
uint64_t
size
)
{
{
uint64_t
j
;
uint64_t
str_i
=
0
,
str_j
=
0
;
uint64_t
index1
,
index2
;
plist_data_t
data
=
plist_new_plist_data
();
plist_data_t
data
=
plist_new_plist_data
();
data
->
type
=
PLIST_DICT
;
data
->
type
=
PLIST_DICT
;
data
->
length
=
size
;
data
->
length
=
size
;
data
->
buff
=
(
uint8_t
*
)
malloc
(
sizeof
(
uint8_t
)
*
size
*
ref_size
*
2
);
memcpy
(
data
->
buff
,
bnode
,
sizeof
(
uint8_t
)
*
size
*
ref_size
*
2
);
return
node_create
(
NULL
,
data
);
plist_t
node
=
node_create
(
NULL
,
data
);
for
(
j
=
0
;
j
<
data
->
length
;
j
++
)
{
str_i
=
j
*
bplist
->
dict_size
;
str_j
=
(
j
+
size
)
*
bplist
->
dict_size
;
index1
=
UINT_TO_HOST
((
*
bnode
)
+
str_i
,
bplist
->
dict_size
);
index2
=
UINT_TO_HOST
((
*
bnode
)
+
str_j
,
bplist
->
dict_size
);
if
(
index1
>=
bplist
->
num_objects
)
{
plist_free
(
node
);
return
NULL
;
}
if
(
index2
>=
bplist
->
num_objects
)
{
plist_free
(
node
);
return
NULL
;
}
/* process key node */
plist_t
key
=
parse_bin_node_at_index
(
bplist
,
index1
);
if
(
!
key
)
{
plist_free
(
node
);
return
NULL
;
}
/* enforce key type */
plist_get_data
(
key
)
->
type
=
PLIST_KEY
;
if
(
!
plist_get_data
(
key
)
->
strval
)
{
fprintf
(
stderr
,
"ERROR: Malformed binary plist dict, invalid key node encountered!
\n
"
);
plist_free
(
key
);
plist_free
(
node
);
return
NULL
;
}
/* process value node */
plist_t
val
=
parse_bin_node_at_index
(
bplist
,
index2
);
if
(
!
val
)
{
plist_free
(
key
);
plist_free
(
node
);
return
NULL
;
}
node_attach
(
node
,
key
);
node_attach
(
node
,
val
);
}
return
node
;
}
}
static
plist_t
parse_array_node
(
char
*
bnode
,
uint64_t
size
,
uint32_t
ref_
size
)
static
plist_t
parse_array_node
(
struct
bplist_data
*
bplist
,
const
char
**
bnode
,
uint64_t
size
)
{
{
uint64_t
j
;
uint32_t
str_j
=
0
;
uint32_t
index1
;
plist_data_t
data
=
plist_new_plist_data
();
plist_data_t
data
=
plist_new_plist_data
();
data
->
type
=
PLIST_ARRAY
;
data
->
type
=
PLIST_ARRAY
;
data
->
length
=
size
;
data
->
length
=
size
;
data
->
buff
=
(
uint8_t
*
)
malloc
(
sizeof
(
uint8_t
)
*
size
*
ref_size
);
memcpy
(
data
->
buff
,
bnode
,
sizeof
(
uint8_t
)
*
size
*
ref_size
);
return
node_create
(
NULL
,
data
);
plist_t
node
=
node_create
(
NULL
,
data
);
for
(
j
=
0
;
j
<
data
->
length
;
j
++
)
{
str_j
=
j
*
bplist
->
dict_size
;
index1
=
UINT_TO_HOST
((
*
bnode
)
+
str_j
,
bplist
->
dict_size
);
if
(
index1
>=
bplist
->
num_objects
)
{
plist_free
(
node
);
return
NULL
;
}
/* process value node */
plist_t
val
=
parse_bin_node_at_index
(
bplist
,
index1
);
if
(
!
val
)
{
plist_free
(
node
);
return
NULL
;
}
node_attach
(
node
,
val
);
}
return
node
;
}
}
static
plist_t
parse_uid_node
(
c
har
*
bnode
,
uint8_t
size
,
char
**
next_object
)
static
plist_t
parse_uid_node
(
c
onst
char
**
bnode
,
uint8_t
size
)
{
{
plist_data_t
data
=
plist_new_plist_data
();
plist_data_t
data
=
plist_new_plist_data
();
...
@@ -422,7 +505,7 @@ static plist_t parse_uid_node(char *bnode, uint8_t size, char **next_object)
...
@@ -422,7 +505,7 @@ static plist_t parse_uid_node(char *bnode, uint8_t size, char **next_object)
case
sizeof
(
uint16_t
):
case
sizeof
(
uint16_t
):
case
sizeof
(
uint32_t
):
case
sizeof
(
uint32_t
):
case
sizeof
(
uint64_t
):
case
sizeof
(
uint64_t
):
memcpy
(
&
data
->
intval
,
bnode
,
size
);
memcpy
(
&
data
->
intval
,
*
bnode
,
size
);
data
->
intval
=
UINT_TO_HOST
(
&
data
->
intval
,
size
);
data
->
intval
=
UINT_TO_HOST
(
&
data
->
intval
,
size
);
break
;
break
;
default:
default:
...
@@ -430,15 +513,13 @@ static plist_t parse_uid_node(char *bnode, uint8_t size, char **next_object)
...
@@ -430,15 +513,13 @@ static plist_t parse_uid_node(char *bnode, uint8_t size, char **next_object)
return
NULL
;
return
NULL
;
};
};
*
next_object
=
bnode
+
size
;
data
->
type
=
PLIST_UID
;
data
->
type
=
PLIST_UID
;
data
->
length
=
sizeof
(
uint64_t
);
data
->
length
=
sizeof
(
uint64_t
);
return
node_create
(
NULL
,
data
);
return
node_create
(
NULL
,
data
);
}
}
static
plist_t
parse_bin_node
(
struct
bplist_data
*
bplist
,
const
char
**
object
)
static
plist_t
parse_bin_node
(
char
*
object
,
uint8_t
dict_size
,
char
**
next_object
)
{
{
uint16_t
type
=
0
;
uint16_t
type
=
0
;
uint64_t
size
=
0
;
uint64_t
size
=
0
;
...
@@ -446,9 +527,9 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
...
@@ -446,9 +527,9 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
if
(
!
object
)
if
(
!
object
)
return
NULL
;
return
NULL
;
type
=
(
*
object
)
&
0xF0
;
type
=
(
*
*
object
)
&
BPLIST_MASK
;
size
=
(
*
object
)
&
0x0F
;
size
=
(
*
*
object
)
&
BPLIST_FILL
;
object
++
;
(
*
object
)
++
;
switch
(
type
)
switch
(
type
)
{
{
...
@@ -481,7 +562,7 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
...
@@ -481,7 +562,7 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
}
}
case
BPLIST_UINT
:
case
BPLIST_UINT
:
return
parse_uint_node
(
object
,
size
,
next_object
);
return
parse_uint_node
(
object
,
size
);
case
BPLIST_REAL
:
case
BPLIST_REAL
:
return
parse_real_node
(
object
,
size
);
return
parse_real_node
(
object
,
size
);
...
@@ -493,9 +574,8 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
...
@@ -493,9 +574,8 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
return
parse_date_node
(
object
,
size
);
return
parse_date_node
(
object
,
size
);
case
BPLIST_DATA
:
case
BPLIST_DATA
:
if
(
0x0F
==
size
)
if
(
BPLIST_FILL
==
size
)
{
{
plist_t
size_node
=
parse_bin_node
(
bplist
,
object
);
plist_t
size_node
=
parse_bin_node
(
object
,
dict_size
,
&
object
);
if
(
plist_get_node_type
(
size_node
)
!=
PLIST_UINT
)
if
(
plist_get_node_type
(
size_node
)
!=
PLIST_UINT
)
return
NULL
;
return
NULL
;
plist_get_uint_val
(
size_node
,
&
size
);
plist_get_uint_val
(
size_node
,
&
size
);
...
@@ -504,9 +584,8 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
...
@@ -504,9 +584,8 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
return
parse_data_node
(
object
,
size
);
return
parse_data_node
(
object
,
size
);
case
BPLIST_STRING
:
case
BPLIST_STRING
:
if
(
0x0F
==
size
)
if
(
BPLIST_FILL
==
size
)
{
{
plist_t
size_node
=
parse_bin_node
(
bplist
,
object
);
plist_t
size_node
=
parse_bin_node
(
object
,
dict_size
,
&
object
);
if
(
plist_get_node_type
(
size_node
)
!=
PLIST_UINT
)
if
(
plist_get_node_type
(
size_node
)
!=
PLIST_UINT
)
return
NULL
;
return
NULL
;
plist_get_uint_val
(
size_node
,
&
size
);
plist_get_uint_val
(
size_node
,
&
size
);
...
@@ -515,9 +594,8 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
...
@@ -515,9 +594,8 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
return
parse_string_node
(
object
,
size
);
return
parse_string_node
(
object
,
size
);
case
BPLIST_UNICODE
:
case
BPLIST_UNICODE
:
if
(
0x0F
==
size
)
if
(
BPLIST_FILL
==
size
)
{
{
plist_t
size_node
=
parse_bin_node
(
bplist
,
object
);
plist_t
size_node
=
parse_bin_node
(
object
,
dict_size
,
&
object
);
if
(
plist_get_node_type
(
size_node
)
!=
PLIST_UINT
)
if
(
plist_get_node_type
(
size_node
)
!=
PLIST_UINT
)
return
NULL
;
return
NULL
;
plist_get_uint_val
(
size_node
,
&
size
);
plist_get_uint_val
(
size_node
,
&
size
);
...
@@ -525,76 +603,64 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
...
@@ -525,76 +603,64 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
}
}
return
parse_unicode_node
(
object
,
size
);
return
parse_unicode_node
(
object
,
size
);
case
BPLIST_
UNK_0x70
:
case
BPLIST_
SET
:
case
BPLIST_ARRAY
:
case
BPLIST_ARRAY
:
if
(
0x0F
==
size
)
if
(
BPLIST_FILL
==
size
)
{
{
plist_t
size_node
=
parse_bin_node
(
bplist
,
object
);
plist_t
size_node
=
parse_bin_node
(
object
,
dict_size
,
&
object
);
if
(
plist_get_node_type
(
size_node
)
!=
PLIST_UINT
)
if
(
plist_get_node_type
(
size_node
)
!=
PLIST_UINT
)
return
NULL
;
return
NULL
;
plist_get_uint_val
(
size_node
,
&
size
);
plist_get_uint_val
(
size_node
,
&
size
);
plist_free
(
size_node
);
plist_free
(
size_node
);
}
}
return
parse_array_node
(
object
,
size
,
dict_
size
);
return
parse_array_node
(
bplist
,
object
,
size
);
case
BPLIST_UID
:
case
BPLIST_UID
:
return
parse_uid_node
(
object
,
size
,
next_object
);
return
parse_uid_node
(
object
,
size
);
case
BPLIST_SET
:
case
BPLIST_DICT
:
case
BPLIST_DICT
:
if
(
0x0F
==
size
)
if
(
BPLIST_FILL
==
size
)
{
{
plist_t
size_node
=
parse_bin_node
(
bplist
,
object
);
plist_t
size_node
=
parse_bin_node
(
object
,
dict_size
,
&
object
);
if
(
plist_get_node_type
(
size_node
)
!=
PLIST_UINT
)
if
(
plist_get_node_type
(
size_node
)
!=
PLIST_UINT
)
return
NULL
;
return
NULL
;
plist_get_uint_val
(
size_node
,
&
size
);
plist_get_uint_val
(
size_node
,
&
size
);
plist_free
(
size_node
);
plist_free
(
size_node
);
}
}
return
parse_dict_node
(
object
,
size
,
dict_
size
);
return
parse_dict_node
(
bplist
,
object
,
size
);
default:
default:
return
NULL
;
return
NULL
;
}
}
return
NULL
;
return
NULL
;
}
}
static
void
*
copy_plist_data
(
const
void
*
src
)
static
plist_t
parse_bin_node_at_index
(
struct
bplist_data
*
bplist
,
uint32_t
node_index
)
{
{
plist_data_t
srcdata
=
(
plist_data_t
)
src
;
int
i
;
plist_data_t
dstdata
=
plist_new_plist_data
();
const
char
*
ptr
;
plist_t
plist
;
dstdata
->
type
=
srcdata
->
type
;
ptr
=
bplist
->
data
+
UINT_TO_HOST
(
bplist
->
offset_table
+
node_index
*
bplist
->
offset_size
,
bplist
->
offset_size
);
dstdata
->
length
=
srcdata
->
length
;
/* make sure the node offset is in a sane range */
switch
(
dstdata
->
type
)
if
((
ptr
<
bplist
->
data
)
||
(
ptr
>=
bplist
->
offset_table
))
{
{
return
NULL
;
case
PLIST_BOOLEAN
:
dstdata
->
boolval
=
srcdata
->
boolval
;
break
;
case
PLIST_UINT
:
dstdata
->
intval
=
srcdata
->
intval
;
break
;
case
PLIST_DATE
:
dstdata
->
timeval
.
tv_sec
=
srcdata
->
timeval
.
tv_sec
;
dstdata
->
timeval
.
tv_usec
=
srcdata
->
timeval
.
tv_usec
;
break
;
case
PLIST_REAL
:
dstdata
->
realval
=
srcdata
->
realval
;
break
;
case
PLIST_KEY
:
case
PLIST_STRING
:
dstdata
->
strval
=
strdup
(
srcdata
->
strval
);
break
;
case
PLIST_DATA
:
dstdata
->
buff
=
(
uint8_t
*
)
malloc
(
sizeof
(
uint8_t
)
*
srcdata
->
length
);
memcpy
(
dstdata
->
buff
,
srcdata
->
buff
,
sizeof
(
uint8_t
)
*
srcdata
->
length
);
break
;
case
PLIST_UID
:
dstdata
->
intval
=
srcdata
->
intval
;
break
;
default:
break
;
}
}
return
dstdata
;
/* store node_index for current recursion level */
bplist
->
used_indexes
[
bplist
->
level
]
=
node_index
;
/* recursion check */
if
(
bplist
->
level
>
0
)
{
for
(
i
=
bplist
->
level
-
1
;
i
>=
0
;
i
--
)
{
if
(
bplist
->
used_indexes
[
i
]
==
bplist
->
used_indexes
[
bplist
->
level
])
{
fprintf
(
stderr
,
"Recursion detected in binary plist. Aborting.
\n
"
);
return
NULL
;
}
}
}
/* finally parse node */
bplist
->
level
++
;
plist
=
parse_bin_node
(
bplist
,
&
ptr
);
bplist
->
level
--
;
return
plist
;
}
}
PLIST_API
void
plist_from_bin
(
const
char
*
plist_bin
,
uint32_t
length
,
plist_t
*
plist
)
PLIST_API
void
plist_from_bin
(
const
char
*
plist_bin
,
uint32_t
length
,
plist_t
*
plist
)
...
@@ -602,19 +668,11 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t *
...
@@ -602,19 +668,11 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t *
char
*
trailer
=
NULL
;
char
*
trailer
=
NULL
;
uint8_t
offset_size
=
0
;
uint8_t
offset_size
=
0
;
uint8_t
dict_
param_
size
=
0
;
uint8_t
dict_size
=
0
;
uint64_t
num_objects
=
0
;
uint64_t
num_objects
=
0
;
uint64_t
root_object
=
0
;
uint64_t
root_object
=
0
;
uint64_t
offset_table_index
=
0
;
uint64_t
offset_table_index
=
0
;
plist_t
*
nodeslist
=
NULL
;
uint64_t
i
=
0
;
uint64_t
current_offset
=
0
;
char
*
offset_table
=
NULL
;
uint32_t
j
=
0
,
str_i
=
0
,
str_j
=
0
;
uint32_t
index1
=
0
,
index2
=
0
;
//first check we have enough data
//first check we have enough data
if
(
!
(
length
>=
BPLIST_MAGIC_SIZE
+
BPLIST_VERSION_SIZE
+
BPLIST_TRL_SIZE
))
if
(
!
(
length
>=
BPLIST_MAGIC_SIZE
+
BPLIST_VERSION_SIZE
+
BPLIST_TRL_SIZE
))
return
;
return
;
...
@@ -629,7 +687,7 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t *
...
@@ -629,7 +687,7 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t *
trailer
=
(
char
*
)
(
plist_bin
+
(
length
-
BPLIST_TRL_SIZE
));
trailer
=
(
char
*
)
(
plist_bin
+
(
length
-
BPLIST_TRL_SIZE
));
offset_size
=
trailer
[
BPLIST_TRL_OFFSIZE_IDX
];
offset_size
=
trailer
[
BPLIST_TRL_OFFSIZE_IDX
];
dict_
param_
size
=
trailer
[
BPLIST_TRL_PARMSIZE_IDX
];
dict_size
=
trailer
[
BPLIST_TRL_PARMSIZE_IDX
];
num_objects
=
be64dec
(
trailer
+
BPLIST_TRL_NUMOBJ_IDX
);
num_objects
=
be64dec
(
trailer
+
BPLIST_TRL_NUMOBJ_IDX
);
root_object
=
be64dec
(
trailer
+
BPLIST_TRL_ROOTOBJ_IDX
);
root_object
=
be64dec
(
trailer
+
BPLIST_TRL_ROOTOBJ_IDX
);
offset_table_index
=
be64dec
(
trailer
+
BPLIST_TRL_OFFTAB_IDX
);
offset_table_index
=
be64dec
(
trailer
+
BPLIST_TRL_OFFTAB_IDX
);
...
@@ -637,122 +695,22 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t *
...
@@ -637,122 +695,22 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t *
if
(
num_objects
==
0
)
if
(
num_objects
==
0
)
return
;
return
;
//allocate serialized array of nodes
if
(
root_object
>=
num_objects
)
nodeslist
=
(
plist_t
*
)
malloc
(
sizeof
(
plist_t
)
*
num_objects
);
if
(
!
nodeslist
)
return
;
return
;
//parse serialized nodes
struct
bplist_data
bplist
;
offset_table
=
(
char
*
)
(
plist_bin
+
offset_table_index
);
bplist
.
data
=
plist_bin
;
for
(
i
=
0
;
i
<
num_objects
;
i
++
)
bplist
.
size
=
length
;
{
bplist
.
num_objects
=
num_objects
;
char
*
obj
=
NULL
;
bplist
.
dict_size
=
dict_size
;
current_offset
=
UINT_TO_HOST
(
offset_table
+
i
*
offset_size
,
offset_size
);
bplist
.
offset_size
=
offset_size
;
bplist
.
offset_table
=
(
char
*
)
(
plist_bin
+
offset_table_index
);
obj
=
(
char
*
)
(
plist_bin
+
current_offset
);
bplist
.
level
=
0
;
nodeslist
[
i
]
=
parse_bin_node
(
obj
,
dict_param_size
,
&
obj
);
bplist
.
used_indexes
=
(
uint32_t
*
)
malloc
(
sizeof
(
uint32_t
)
*
num_objects
);
}
//setup children for structured types
for
(
i
=
0
;
i
<
num_objects
;
i
++
)
{
plist_data_t
data
=
plist_get_data
(
nodeslist
[
i
]);
if
(
!
data
)
{
break
;
}
switch
(
data
->
type
)
*
plist
=
parse_bin_node_at_index
(
&
bplist
,
root_object
);
{
case
PLIST_DICT
:
for
(
j
=
0
;
j
<
data
->
length
;
j
++
)
{
node_t
*
n
=
NULL
;
str_i
=
j
*
dict_param_size
;
str_j
=
(
j
+
data
->
length
)
*
dict_param_size
;
index1
=
UINT_TO_HOST
(
data
->
buff
+
str_i
,
dict_param_size
);
index2
=
UINT_TO_HOST
(
data
->
buff
+
str_j
,
dict_param_size
);
// process key node
if
(
index1
<
num_objects
)
{
// is node already attached?
if
(
NODE_IS_ROOT
(
nodeslist
[
index1
]))
{
// use original
n
=
nodeslist
[
index1
];
}
else
{
// use a copy, because this node is already attached elsewhere
n
=
node_copy_deep
(
nodeslist
[
index1
],
copy_plist_data
);
}
// enforce key type
plist_get_data
(
n
)
->
type
=
PLIST_KEY
;
// attach key node
node_attach
(
nodeslist
[
i
],
n
);
}
// process value node
if
(
index2
<
num_objects
)
{
// is node already attached?
if
(
NODE_IS_ROOT
(
nodeslist
[
index2
]))
{
// use original
n
=
nodeslist
[
index2
];
}
else
{
// use a copy, because this node is already attached elsewhere
n
=
node_copy_deep
(
nodeslist
[
index2
],
copy_plist_data
);
// ensure key type is never used for values, especially if we copy a key node
if
(
plist_get_data
(
n
)
->
type
==
PLIST_KEY
)
{
plist_get_data
(
n
)
->
type
=
PLIST_STRING
;
}
}
// attach value node
node_attach
(
nodeslist
[
i
],
n
);
}
}
break
;
case
PLIST_ARRAY
:
free
(
bplist
.
used_indexes
);
for
(
j
=
0
;
j
<
data
->
length
;
j
++
)
{
str_j
=
j
*
dict_param_size
;
index1
=
UINT_TO_HOST
(
data
->
buff
+
str_j
,
dict_param_size
);
if
(
index1
<
num_objects
)
{
if
(
NODE_IS_ROOT
(
nodeslist
[
index1
]))
node_attach
(
nodeslist
[
i
],
nodeslist
[
index1
]);
else
node_attach
(
nodeslist
[
i
],
node_copy_deep
(
nodeslist
[
index1
],
copy_plist_data
));
}
}
break
;
default:
break
;
}
}
*
plist
=
nodeslist
[
root_object
];
// free unreferenced nodes that would otherwise leak memory
for
(
i
=
0
;
i
<
num_objects
;
i
++
)
{
plist_data_t
data
=
plist_get_data
(
nodeslist
[
i
]);
if
((
data
->
type
==
PLIST_DICT
)
||
(
data
->
type
==
PLIST_ARRAY
))
{
free
(
data
->
buff
);
data
->
buff
=
NULL
;
}
if
(
i
==
root_object
)
continue
;
node_t
*
node
=
(
node_t
*
)
nodeslist
[
i
];
if
(
node
&&
NODE_IS_ROOT
(
node
))
{
plist_free
(
node
);
}
}
free
(
nodeslist
);
}
}
static
unsigned
int
plist_data_hash
(
const
void
*
key
)
static
unsigned
int
plist_data_hash
(
const
void
*
key
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment