summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/bplist.c2
-rw-r--r--src/common.c115
-rw-r--r--src/common.h34
-rw-r--r--src/jplist.c74
-rw-r--r--src/oplist.c71
-rw-r--r--src/out-default.c87
-rw-r--r--src/out-limd.c87
-rw-r--r--src/out-plutil.c156
-rw-r--r--src/plist.c2
-rw-r--r--src/time64.h7
-rw-r--r--src/xplist.c71
12 files changed, 265 insertions, 442 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 1a416ad..ce4f931 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,6 +21,7 @@ libplist_2_0_la_SOURCES = \
ptrarray.c ptrarray.h \
time64.c time64.h \
time64_limits.h \
+ common.c common.h \
xplist.c \
bplist.c \
jsmn.c jsmn.h \
diff --git a/src/bplist.c b/src/bplist.c
index 1187c7a..7b08532 100644
--- a/src/bplist.c
+++ b/src/bplist.c
@@ -854,7 +854,7 @@ static plist_t parse_bin_node_at_index(struct bplist_data *bplist, uint32_t node
uint64_t node_offset = UINT_TO_HOST(idx_ptr, bplist->offset_size);
if (node_offset > (uint64_t)bplist->size) {
- PLIST_BIN_ERR("node offset overflow (%llu)\n", node_offset);
+ PLIST_BIN_ERR("node offset overflow (%" PRIu64 ")\n", node_offset);
bplist->err = PLIST_ERR_PARSE;
return NULL;
}
diff --git a/src/common.c b/src/common.c
new file mode 100644
index 0000000..810c2e0
--- /dev/null
+++ b/src/common.c
@@ -0,0 +1,115 @@
+/*
+ * common.c
+ * contains some common functions
+ *
+ * Copyright (c) 2026 Nikias Bassen, All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <math.h>
+#include <stdio.h>
+#include <stdint.h>
+#include "common.h"
+
+size_t dtostr(char *buf, size_t bufsize, double realval)
+{
+ int slen = 0;
+ if (isnan(realval)) {
+ slen = snprintf(buf, bufsize, "nan");
+ } else if (isinf(realval)) {
+ slen = snprintf(buf, bufsize, "%cinfinity", (realval > 0.0) ? '+' : '-');
+ } else if (realval == 0.0f) {
+ slen = snprintf(buf, bufsize, "0.0");
+ } else {
+ slen = snprintf(buf, bufsize, "%.*g", 17, realval);
+ if (slen < 0) {
+ return 0;
+ }
+ if (!buf || bufsize == 0) {
+ return (size_t)slen;
+ }
+ size_t len = (size_t)slen;
+ if (len >= bufsize) {
+ len = bufsize - 1;
+ }
+ size_t i = 0;
+ for (i = 0; i < len; i++) {
+ if (buf[i] == ',') {
+ buf[i] = '.';
+ break;
+ } else if (buf[i] == '.') {
+ break;
+ }
+ }
+ return len;
+ }
+ if (slen < 0) {
+ return 0;
+ }
+ return (size_t)slen;
+}
+
+/* based on https://stackoverflow.com/a/4143288 */
+#define PO10i_LIMIT (INT64_MAX/10)
+int num_digits_i(int64_t i)
+{
+ int n;
+ int64_t po10;
+ n=1;
+ if (i < 0) {
+ i = (i == INT64_MIN) ? INT64_MAX : -i;
+ n++;
+ }
+ po10=10;
+ while (i>=po10) {
+ n++;
+ if (po10 > PO10i_LIMIT) break;
+ po10*=10;
+ }
+ return n;
+}
+#undef PO10i_LIMIT
+
+/* based on https://stackoverflow.com/a/4143288 */
+#define PO10u_LIMIT (UINT64_MAX/10)
+int num_digits_u(uint64_t i)
+{
+ int n;
+ uint64_t po10;
+ n=1;
+ po10=10;
+ while (i>=po10) {
+ n++;
+ if (po10 > PO10u_LIMIT) break;
+ po10*=10;
+ }
+ return n;
+}
+#undef PO10u_LIMIT
+
+int plist_real_to_time64(double realval, Time64_T *timev)
+{
+ if (!timev || !isfinite(realval)) {
+ return -1;
+ }
+
+ if (realval < (double)TIME64_MIN - (double)MAC_EPOCH ||
+ realval > (double)TIME64_MAX - (double)MAC_EPOCH) {
+ return -1;
+ }
+
+ *timev = (Time64_T)realval + MAC_EPOCH;
+ return 0;
+}
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..ffaa78c
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,34 @@
+/*
+ * common.h
+ * contains some common functions
+ *
+ * Copyright (c) 2026 Nikias Bassen, All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <stddef.h>
+#include "time64.h"
+
+#define MAC_EPOCH 978307200
+
+size_t dtostr(char *buf, size_t bufsize, double realval);
+int num_digits_i(int64_t i);
+int num_digits_u(uint64_t i);
+int plist_real_to_time64(double realval, Time64_T *timev);
+
+#endif
diff --git a/src/jplist.c b/src/jplist.c
index 410d4b3..c29f760 100644
--- a/src/jplist.c
+++ b/src/jplist.c
@@ -41,8 +41,7 @@
#include "hashtable.h"
#include "base64.h"
#include "time64.h"
-
-#define MAC_EPOCH 978307200
+#include "common.h"
#ifdef DEBUG
static int plist_json_debug = 0;
@@ -95,30 +94,6 @@ static char* strndup(const char* str, size_t len)
#endif
#endif
-static size_t dtostr(char *buf, size_t bufsize, double realval)
-{
- size_t len = 0;
- if (isnan(realval)) {
- len = snprintf(buf, bufsize, "nan");
- } else if (isinf(realval)) {
- len = snprintf(buf, bufsize, "%cinfinity", (realval > 0.0) ? '+' : '-');
- } else if (realval == 0.0f) {
- len = snprintf(buf, bufsize, "0.0");
- } else {
- size_t i = 0;
- len = snprintf(buf, bufsize, "%.*g", 17, realval);
- for (i = 0; buf && i < len; i++) {
- if (buf[i] == ',') {
- buf[i] = '.';
- break;
- } else if (buf[i] == '.') {
- break;
- }
- }
- }
- return len;
-}
-
static plist_err_t node_to_json(node_t node, bytearray_t **outbuf, uint32_t depth, int prettify, int coerce)
{
plist_data_t node_data = NULL;
@@ -282,7 +257,11 @@ static plist_err_t node_to_json(node_t node, bytearray_t **outbuf, uint32_t dept
break;
case PLIST_DATE:
if (coerce) {
- Time64_T timev = (Time64_T)node_data->realval + MAC_EPOCH;
+ Time64_T timev;
+ if (plist_real_to_time64(node_data->realval, &timev) < 0) {
+ PLIST_JSON_WRITE_ERR("Encountered invalid date value %f\n", node_data->realval);
+ return PLIST_ERR_INVALID_ARG;
+ }
struct TM _btime;
struct TM *btime = gmtime64_r(&timev, &_btime);
char datebuf[32];
@@ -325,44 +304,6 @@ static plist_err_t node_to_json(node_t node, bytearray_t **outbuf, uint32_t dept
return PLIST_ERR_SUCCESS;
}
-#define PO10i_LIMIT (INT64_MAX/10)
-
-/* based on https://stackoverflow.com/a/4143288 */
-static int num_digits_i(int64_t i)
-{
- int n;
- int64_t po10;
- n=1;
- if (i < 0) {
- i = (i == INT64_MIN) ? INT64_MAX : -i;
- n++;
- }
- po10=10;
- while (i>=po10) {
- n++;
- if (po10 > PO10i_LIMIT) break;
- po10*=10;
- }
- return n;
-}
-
-#define PO10u_LIMIT (UINT64_MAX/10)
-
-/* based on https://stackoverflow.com/a/4143288 */
-static int num_digits_u(uint64_t i)
-{
- int n;
- uint64_t po10;
- n=1;
- po10=10;
- while (i>=po10) {
- n++;
- if (po10 > PO10u_LIMIT) break;
- po10*=10;
- }
- return n;
-}
-
static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify, int coerce, hashtable_t *visited)
{
plist_data_t data;
@@ -556,6 +497,7 @@ typedef struct {
static int64_t parse_decimal(const char* str, const char* str_end, char** endp)
{
+ const uint64_t po10i_limit = INT64_MAX / 10;
uint64_t MAX = INT64_MAX;
uint64_t x = 0;
int is_neg = 0;
@@ -571,7 +513,7 @@ static int64_t parse_decimal(const char* str, const char* str_end, char** endp)
MAX++;
}
while (*endp < str_end && isdigit(**endp)) {
- if (x > PO10i_LIMIT) {
+ if (x > po10i_limit) {
x = MAX;
break;
}
diff --git a/src/oplist.c b/src/oplist.c
index 3c48b3a..77a99cd 100644
--- a/src/oplist.c
+++ b/src/oplist.c
@@ -39,8 +39,7 @@
#include "strbuf.h"
#include "time64.h"
#include "hashtable.h"
-
-#define MAC_EPOCH 978307200
+#include "common.h"
#ifdef DEBUG
static int plist_ostep_debug = 0;
@@ -93,30 +92,6 @@ static char* strndup(const char* str, size_t len)
#endif
#endif
-static size_t dtostr(char *buf, size_t bufsize, double realval)
-{
- size_t len = 0;
- if (isnan(realval)) {
- len = snprintf(buf, bufsize, "nan");
- } else if (isinf(realval)) {
- len = snprintf(buf, bufsize, "%cinfinity", (realval > 0.0) ? '+' : '-');
- } else if (realval == 0.0f) {
- len = snprintf(buf, bufsize, "0.0");
- } else {
- size_t i = 0;
- len = snprintf(buf, bufsize, "%.*g", 17, realval);
- for (i = 0; buf && i < len; i++) {
- if (buf[i] == ',') {
- buf[i] = '.';
- break;
- } else if (buf[i] == '.') {
- break;
- }
- }
- }
- return len;
-}
-
static const char allowed_unquoted_chars[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -326,7 +301,11 @@ static plist_err_t node_to_openstep(node_t node, bytearray_t **outbuf, uint32_t
break;
case PLIST_DATE:
if (coerce) {
- Time64_T timev = (Time64_T)node_data->realval + MAC_EPOCH;
+ Time64_T timev;
+ if (plist_real_to_time64(node_data->realval, &timev) < 0) {
+ PLIST_OSTEP_WRITE_ERR("Encountered invalid date value %f\n", node_data->realval);
+ return PLIST_ERR_INVALID_ARG;
+ }
struct TM _btime;
struct TM *btime = gmtime64_r(&timev, &_btime);
char datebuf[32];
@@ -371,44 +350,6 @@ static plist_err_t node_to_openstep(node_t node, bytearray_t **outbuf, uint32_t
return PLIST_ERR_SUCCESS;
}
-#define PO10i_LIMIT (INT64_MAX/10)
-
-/* based on https://stackoverflow.com/a/4143288 */
-static int num_digits_i(int64_t i)
-{
- int n;
- int64_t po10;
- n=1;
- if (i < 0) {
- i = (i == INT64_MIN) ? INT64_MAX : -i;
- n++;
- }
- po10=10;
- while (i>=po10) {
- n++;
- if (po10 > PO10i_LIMIT) break;
- po10*=10;
- }
- return n;
-}
-
-#define PO10u_LIMIT (UINT64_MAX/10)
-
-/* based on https://stackoverflow.com/a/4143288 */
-static int num_digits_u(uint64_t i)
-{
- int n;
- uint64_t po10;
- n=1;
- po10=10;
- while (i>=po10) {
- n++;
- if (po10 > PO10u_LIMIT) break;
- po10*=10;
- }
- return n;
-}
-
static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify, int coerce, hashtable_t *visited)
{
plist_data_t data;
diff --git a/src/out-default.c b/src/out-default.c
index 676a677..13b9d9c 100644
--- a/src/out-default.c
+++ b/src/out-default.c
@@ -39,46 +39,7 @@
#include "strbuf.h"
#include "time64.h"
#include "hashtable.h"
-
-#define MAC_EPOCH 978307200
-
-static size_t dtostr(char *buf, size_t bufsize, double realval)
-{
- int slen = 0;
- if (isnan(realval)) {
- slen = snprintf(buf, bufsize, "nan");
- } else if (isinf(realval)) {
- slen = snprintf(buf, bufsize, "%cinfinity", (realval > 0.0) ? '+' : '-');
- } else if (realval == 0.0f) {
- slen = snprintf(buf, bufsize, "0.0");
- } else {
- slen = snprintf(buf, bufsize, "%.*g", 17, realval);
- if (slen < 0) {
- return 0;
- }
- if (!buf || bufsize == 0) {
- return (size_t)slen;
- }
- size_t len = (size_t)slen;
- if (len >= bufsize) {
- len = bufsize - 1;
- }
- size_t i = 0;
- for (i = 0; i < len; i++) {
- if (buf[i] == ',') {
- buf[i] = '.';
- break;
- } else if (buf[i] == '.') {
- break;
- }
- }
- return len;
- }
- if (slen < 0) {
- return 0;
- }
- return (size_t)slen;
-}
+#include "common.h"
static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t depth, uint32_t indent, int partial_data)
{
@@ -270,7 +231,13 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
break;
case PLIST_DATE:
{
- Time64_T timev = (Time64_T)node_data->realval + MAC_EPOCH;
+ Time64_T timev;
+ if (plist_real_to_time64(node_data->realval, &timev) < 0) {
+#if DEBUG
+ fprintf(stderr, "libplist: ERROR: Encountered invalid date value %f\n", node_data->realval);
+#endif
+ return PLIST_ERR_INVALID_ARG;
+ }
struct TM _btime;
struct TM *btime = gmtime64_r(&timev, &_btime);
if (btime) {
@@ -313,44 +280,6 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
return PLIST_ERR_SUCCESS;
}
-#define PO10i_LIMIT (INT64_MAX/10)
-
-/* based on https://stackoverflow.com/a/4143288 */
-static int num_digits_i(int64_t i)
-{
- int n;
- int64_t po10;
- n=1;
- if (i < 0) {
- i = (i == INT64_MIN) ? INT64_MAX : -i;
- n++;
- }
- po10=10;
- while (i>=po10) {
- n++;
- if (po10 > PO10i_LIMIT) break;
- po10*=10;
- }
- return n;
-}
-
-#define PO10u_LIMIT (UINT64_MAX/10)
-
-/* based on https://stackoverflow.com/a/4143288 */
-static int num_digits_u(uint64_t i)
-{
- int n;
- uint64_t po10;
- n=1;
- po10=10;
- while (i>=po10) {
- n++;
- if (po10 > PO10u_LIMIT) break;
- po10*=10;
- }
- return n;
-}
-
static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, uint32_t indent, int partial_data, hashtable_t *visited)
{
plist_data_t data;
diff --git a/src/out-limd.c b/src/out-limd.c
index 6d864cb..83a5e26 100644
--- a/src/out-limd.c
+++ b/src/out-limd.c
@@ -41,46 +41,7 @@
#include "time64.h"
#include "base64.h"
#include "hashtable.h"
-
-#define MAC_EPOCH 978307200
-
-static size_t dtostr(char *buf, size_t bufsize, double realval)
-{
- int slen = 0;
- if (isnan(realval)) {
- slen = snprintf(buf, bufsize, "nan");
- } else if (isinf(realval)) {
- slen = snprintf(buf, bufsize, "%cinfinity", (realval > 0.0) ? '+' : '-');
- } else if (realval == 0.0f) {
- slen = snprintf(buf, bufsize, "0.0");
- } else {
- slen = snprintf(buf, bufsize, "%.*g", 17, realval);
- if (slen < 0) {
- return 0;
- }
- if (!buf || bufsize == 0) {
- return (size_t)slen;
- }
- size_t len = (size_t)slen;
- if (len >= bufsize) {
- len = bufsize - 1;
- }
- size_t i = 0;
- for (i = 0; i < len; i++) {
- if (buf[i] == ',') {
- buf[i] = '.';
- break;
- } else if (buf[i] == '.') {
- break;
- }
- }
- return len;
- }
- if (slen < 0) {
- return 0;
- }
- return (size_t)slen;
-}
+#include "common.h"
static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t depth, uint32_t indent)
{
@@ -259,7 +220,13 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
break;
case PLIST_DATE:
{
- Time64_T timev = (Time64_T)node_data->realval + MAC_EPOCH;
+ Time64_T timev;
+ if (plist_real_to_time64(node_data->realval, &timev) < 0) {
+#if DEBUG
+ fprintf(stderr, "libplist: ERROR: Encountered invalid date value %f\n", node_data->realval);
+#endif
+ return PLIST_ERR_INVALID_ARG;
+ }
struct TM _btime;
struct TM *btime = gmtime64_r(&timev, &_btime);
if (btime) {
@@ -304,44 +271,6 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
return PLIST_ERR_SUCCESS;
}
-#define PO10i_LIMIT (INT64_MAX/10)
-
-/* based on https://stackoverflow.com/a/4143288 */
-static int num_digits_i(int64_t i)
-{
- int n;
- int64_t po10;
- n=1;
- if (i < 0) {
- i = (i == INT64_MIN) ? INT64_MAX : -i;
- n++;
- }
- po10=10;
- while (i>=po10) {
- n++;
- if (po10 > PO10i_LIMIT) break;
- po10*=10;
- }
- return n;
-}
-
-#define PO10u_LIMIT (UINT64_MAX/10)
-
-/* based on https://stackoverflow.com/a/4143288 */
-static int num_digits_u(uint64_t i)
-{
- int n;
- uint64_t po10;
- n=1;
- po10=10;
- while (i>=po10) {
- n++;
- if (po10 > PO10u_LIMIT) break;
- po10*=10;
- }
- return n;
-}
-
static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, uint32_t indent, hashtable_t *visited)
{
plist_data_t data;
diff --git a/src/out-plutil.c b/src/out-plutil.c
index bf9e72e..e603f31 100644
--- a/src/out-plutil.c
+++ b/src/out-plutil.c
@@ -39,46 +39,24 @@
#include "strbuf.h"
#include "time64.h"
#include "hashtable.h"
-
-#define MAC_EPOCH 978307200
-
-static size_t dtostr(char *buf, size_t bufsize, double realval)
-{
- size_t len = 0;
- if (isnan(realval)) {
- len = snprintf(buf, bufsize, "nan");
- } else if (isinf(realval)) {
- len = snprintf(buf, bufsize, "%cinfinity", (realval > 0.0) ? '+' : '-');
- } else if (realval == 0.0f) {
- len = snprintf(buf, bufsize, "0.0");
- } else {
- size_t i = 0;
- len = snprintf(buf, bufsize, "%.*g", 17, realval);
- for (i = 0; buf && i < len; i++) {
- if (buf[i] == ',') {
- buf[i] = '.';
- break;
- } else if (buf[i] == '.') {
- break;
- }
- }
- }
- return len;
-}
+#include "common.h"
static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t depth)
{
plist_data_t node_data = NULL;
char *val = NULL;
+ int slen = 0;
size_t val_len = 0;
- uint32_t i = 0;
-
- if (!node)
+ if (!node || !outbuf || !*outbuf) {
return PLIST_ERR_INVALID_ARG;
+ }
node_data = plist_get_data(node);
+ if (!node_data) {
+ return PLIST_ERR_INVALID_ARG;
+ }
switch (node_data->type)
{
@@ -98,17 +76,24 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
case PLIST_INT:
val = (char*)malloc(64);
+ if (!val) return PLIST_ERR_NO_MEM;
if (node_data->length == 16) {
- val_len = snprintf(val, 64, "%" PRIu64, node_data->intval);
+ slen = snprintf(val, 64, "%" PRIu64, node_data->intval);
} else {
- val_len = snprintf(val, 64, "%" PRIi64, node_data->intval);
+ slen = snprintf(val, 64, "%" PRIi64, node_data->intval);
+ }
+ if (slen < 0) {
+ free(val);
+ return PLIST_ERR_UNKNOWN;
}
+ val_len = (size_t)slen;
str_buf_append(*outbuf, val, val_len);
free(val);
break;
case PLIST_REAL:
val = (char*)malloc(64);
+ if (!val) return PLIST_ERR_NO_MEM;
val_len = dtostr(val, 64, node_data->realval);
str_buf_append(*outbuf, val, val_len);
free(val);
@@ -116,6 +101,9 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
case PLIST_STRING:
case PLIST_KEY: {
+ if (!node_data->strval && node_data->length > 0) {
+ return PLIST_ERR_INVALID_ARG;
+ }
const char *charmap[32] = {
"\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007",
"\\b", "\\t", "\\n", "\\u000b", "\\f", "\\r", "\\u000e", "\\u000f",
@@ -124,8 +112,8 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
};
size_t j = 0;
size_t len = 0;
- off_t start = 0;
- off_t cur = 0;
+ size_t start = 0;
+ size_t cur = 0;
str_buf_append(*outbuf, "\"", 1);
@@ -152,14 +140,18 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
str_buf_append(*outbuf, "[", 1);
node_t ch;
uint32_t cnt = 0;
+ uint32_t i;
for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
str_buf_append(*outbuf, "\n", 1);
for (i = 0; i <= depth; i++) {
str_buf_append(*outbuf, " ", 2);
}
char indexbuf[16];
- int l = sprintf(indexbuf, "%u => ", cnt);
- str_buf_append(*outbuf, indexbuf, l);
+ slen = snprintf(indexbuf, sizeof(indexbuf), "%u => ", cnt);
+ if (slen < 0) {
+ return PLIST_ERR_UNKNOWN;
+ }
+ str_buf_append(*outbuf, indexbuf, (size_t)slen);
plist_err_t res = node_to_string(ch, outbuf, depth+1);
if (res < 0) {
return res;
@@ -178,6 +170,7 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
str_buf_append(*outbuf, "{", 1);
node_t ch;
uint32_t cnt = 0;
+ uint32_t i;
for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
if (cnt % 2 == 0) {
str_buf_append(*outbuf, "\n", 1);
@@ -204,27 +197,36 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
} break;
case PLIST_DATA:
{
+ if (!node_data->buff && node_data->length > 0) {
+ return PLIST_ERR_INVALID_ARG;
+ }
val = (char*)calloc(1, 48);
+ if (!val) return PLIST_ERR_NO_MEM;
size_t len = node_data->length;
- size_t slen = snprintf(val, 48, "{length = %" PRIu64 ", bytes = 0x", (uint64_t)len);
- str_buf_append(*outbuf, val, slen);
+ slen = snprintf(val, 48, "{length = %" PRIu64 ", bytes = 0x", (uint64_t)len);
+ if (slen < 0) {
+ free(val);
+ return PLIST_ERR_UNKNOWN;
+ }
+ str_buf_append(*outbuf, val, (size_t)slen);
+ size_t j;
if (len <= 24) {
- for (i = 0; i < len; i++) {
- sprintf(val, "%02x", (unsigned char)node_data->buff[i]);
+ for (j = 0; j < len; j++) {
+ snprintf(val, 4, "%02x", (unsigned char)node_data->buff[j]);
str_buf_append(*outbuf, val, 2);
}
} else {
- for (i = 0; i < 16; i++) {
- if (i > 0 && (i % 4 == 0))
+ for (j = 0; j < 16; j++) {
+ if (j > 0 && (j % 4 == 0))
str_buf_append(*outbuf, " ", 1);
- sprintf(val, "%02x", (unsigned char)node_data->buff[i]);
+ snprintf(val, 4, "%02x", (unsigned char)node_data->buff[j]);
str_buf_append(*outbuf, val, 2);
}
str_buf_append(*outbuf, " ... ", 5);
- for (i = len - 8; i < len; i++) {
- sprintf(val, "%02x", (unsigned char)node_data->buff[i]);
+ for (j = len - 8; j < len; j++) {
+ snprintf(val, 4, "%02x", (unsigned char)node_data->buff[j]);
str_buf_append(*outbuf, val, 2);
- if (i > 0 && (i % 4 == 0))
+ if (j > 0 && (j % 4 == 0))
str_buf_append(*outbuf, " ", 1);
}
}
@@ -235,11 +237,18 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
break;
case PLIST_DATE:
{
- Time64_T timev = (Time64_T)node_data->realval + MAC_EPOCH;
+ Time64_T timev;
+ if (plist_real_to_time64(node_data->realval, &timev) < 0) {
+#if DEBUG
+ fprintf(stderr, "libplist: ERROR: Encountered invalid date value %f\n", node_data->realval);
+#endif
+ return PLIST_ERR_INVALID_ARG;
+ }
struct TM _btime;
struct TM *btime = gmtime64_r(&timev, &_btime);
if (btime) {
val = (char*)calloc(1, 26);
+ if (!val) return PLIST_ERR_NO_MEM;
struct tm _tmcopy;
copy_TM64_to_tm(btime, &_tmcopy);
val_len = strftime(val, 26, "%Y-%m-%d %H:%M:%S +0000", &_tmcopy);
@@ -253,11 +262,24 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
break;
case PLIST_UID:
{
- val = (char*)malloc(88);
- val_len = sprintf(val, "<CFKeyedArchiverUID %p [%p]>{value = %" PRIu64 "}", node, node_data, node_data->intval);
+#define UID_FMT "<CFKeyedArchiverUID %p [%p]>{value = %" PRIu64 "}"
+ slen = snprintf(NULL, 0, UID_FMT, node, node_data, node_data->intval);
+ if (slen < 0) {
+ return PLIST_ERR_UNKNOWN;
+ }
+ val_len = (size_t)slen;
+ val = (char*)malloc(val_len + 1);
+ if (!val) return PLIST_ERR_NO_MEM;
+ slen = snprintf(val, val_len+1, UID_FMT, node, node_data, node_data->intval);
+ if (slen < 0 || (size_t)slen > val_len) {
+ free(val);
+ return PLIST_ERR_UNKNOWN;
+ }
+ val_len = (size_t)slen;
str_buf_append(*outbuf, val, val_len);
free(val);
val = NULL;
+#undef UID_FMT
}
break;
default:
@@ -267,44 +289,6 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
return PLIST_ERR_SUCCESS;
}
-#define PO10i_LIMIT (INT64_MAX/10)
-
-/* based on https://stackoverflow.com/a/4143288 */
-static int num_digits_i(int64_t i)
-{
- int n;
- int64_t po10;
- n=1;
- if (i < 0) {
- i = (i == INT64_MIN) ? INT64_MAX : -i;
- n++;
- }
- po10=10;
- while (i>=po10) {
- n++;
- if (po10 > PO10i_LIMIT) break;
- po10*=10;
- }
- return n;
-}
-
-#define PO10u_LIMIT (UINT64_MAX/10)
-
-/* based on https://stackoverflow.com/a/4143288 */
-static int num_digits_u(uint64_t i)
-{
- int n;
- uint64_t po10;
- n=1;
- po10=10;
- while (i>=po10) {
- n++;
- if (po10 > PO10u_LIMIT) break;
- po10*=10;
- }
- return n;
-}
-
static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, hashtable_t *visited)
{
plist_data_t data;
diff --git a/src/plist.c b/src/plist.c
index 7def2b6..05af457 100644
--- a/src/plist.c
+++ b/src/plist.c
@@ -46,7 +46,7 @@
#include <hashtable.h>
#include <ptrarray.h>
-#define MAC_EPOCH 978307200
+#include "common.h"
#ifdef _MSC_VER
typedef SSIZE_T ssize_t;
diff --git a/src/time64.h b/src/time64.h
index 28968c0..2c20ffe 100644
--- a/src/time64.h
+++ b/src/time64.h
@@ -11,6 +11,13 @@ typedef long long Int64;
typedef Int64 Time64_T;
typedef Int64 Year;
+#ifndef TIME64_MIN
+#define TIME64_MIN ((Time64_T)INT64_MIN)
+#endif
+
+#ifndef TIME64_MAX
+#define TIME64_MAX ((Time64_T)INT64_MAX)
+#endif
/* A copy of the tm struct but with a 64 bit year */
struct TM64 {
diff --git a/src/xplist.c b/src/xplist.c
index de5227a..b2c134e 100644
--- a/src/xplist.c
+++ b/src/xplist.c
@@ -48,6 +48,7 @@
#include "strbuf.h"
#include "time64.h"
#include "hashtable.h"
+#include "common.h"
#define XPLIST_KEY "key"
#define XPLIST_KEY_LEN 3
@@ -70,8 +71,6 @@
#define XPLIST_DICT "dict"
#define XPLIST_DICT_LEN 4
-#define MAC_EPOCH 978307200
-
#define MAX_DATA_BYTES_PER_LINE(__i) (((76 - ((__i) << 3)) >> 2) * 3)
static const char XML_PLIST_PROLOG[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
@@ -111,30 +110,6 @@ void plist_xml_set_debug(int debug)
#endif
}
-static size_t dtostr(char *buf, size_t bufsize, double realval)
-{
- size_t len = 0;
- if (isnan(realval)) {
- len = snprintf(buf, bufsize, "nan");
- } else if (isinf(realval)) {
- len = snprintf(buf, bufsize, "%cinfinity", (realval > 0.0) ? '+' : '-');
- } else if (realval == 0.0f) {
- len = snprintf(buf, bufsize, "0.0");
- } else {
- size_t i = 0;
- len = snprintf(buf, bufsize, "%.*g", 17, realval);
- for (i = 0; buf && i < len; i++) {
- if (buf[i] == ',') {
- buf[i] = '.';
- break;
- } else if (buf[i] == '.') {
- break;
- }
- }
- }
- return len;
-}
-
static plist_err_t node_to_xml(node_t node, bytearray_t **outbuf, uint32_t depth)
{
plist_data_t node_data = NULL;
@@ -217,7 +192,11 @@ static plist_err_t node_to_xml(node_t node, bytearray_t **outbuf, uint32_t depth
tag = XPLIST_DATE;
tag_len = XPLIST_DATE_LEN;
{
- Time64_T timev = (Time64_T)node_data->realval + MAC_EPOCH;
+ Time64_T timev;
+ if (plist_real_to_time64(node_data->realval, &timev) < 0) {
+ PLIST_XML_WRITE_ERR("Encountered invalid date value %f\n", node_data->realval);
+ return PLIST_ERR_INVALID_ARG;
+ }
struct TM _btime;
struct TM *btime = gmtime64_r(&timev, &_btime);
if (btime) {
@@ -422,44 +401,6 @@ static int parse_date(const char *strval, struct TM *btime)
return 0;
}
-#define PO10i_LIMIT (INT64_MAX/10)
-
-/* based on https://stackoverflow.com/a/4143288 */
-static int num_digits_i(int64_t i)
-{
- int n;
- int64_t po10;
- n=1;
- if (i < 0) {
- i = (i == INT64_MIN) ? INT64_MAX : -i;
- n++;
- }
- po10=10;
- while (i>=po10) {
- n++;
- if (po10 > PO10i_LIMIT) break;
- po10*=10;
- }
- return n;
-}
-
-#define PO10u_LIMIT (UINT64_MAX/10)
-
-/* based on https://stackoverflow.com/a/4143288 */
-static int num_digits_u(uint64_t i)
-{
- int n;
- uint64_t po10;
- n=1;
- po10=10;
- while (i>=po10) {
- n++;
- if (po10 > PO10u_LIMIT) break;
- po10*=10;
- }
- return n;
-}
-
static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, hashtable_t *visited)
{
plist_data_t data;