From c6b65a24965757ddd59a3a6fb586d5dad9e428b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristian=20Rodr=C3=ADguez?= Date: Tue, 1 Dec 2020 23:22:08 -0300 Subject: [PATCH 1/2] Remove 1000 char xattr limit We need to access xattrs much bigger than 1000, up to the size allowed by the filesystem. --- smbclient.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/smbclient.c b/smbclient.c index a63bad4..a480957 100644 --- a/smbclient.c +++ b/smbclient.c @@ -1663,10 +1663,12 @@ PHP_FUNCTION(smbclient_getxattr) char *url, *name; strsize_t url_len, name_len; int retsize; - char values[1000]; + int xattr_size; zval *zstate; smbc_getxattr_fn smbc_getxattr; php_smbclient_state *state; + char *values = NULL; + ALLOCA_FLAG(use_heap) if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zstate, &url, &url_len, &name, &name_len) == FAILURE) { return; @@ -1676,20 +1678,28 @@ PHP_FUNCTION(smbclient_getxattr) if ((smbc_getxattr = smbc_getFunctionGetxattr(state->ctx)) == NULL) { RETURN_FALSE; } - /* TODO: 1000 chars should be enough for everyone...? - * However, doing an initial blank call to determine the response size - * seems wasteful, and vulnerable to a time-of-check, time-of-use - * error. */ - if ((retsize = smbc_getxattr(state->ctx, url, name, values, sizeof(values))) >= 0) { - if (retsize > sizeof(values)) { - retsize = sizeof(values); - } -#if PHP_MAJOR_VERSION >= 7 - RETURN_STRINGL(values, retsize); -#else - RETURN_STRINGL(values, retsize, 1); -#endif + + xattr_size = smbc_getxattr(state->ctx, url, name, NULL, 0); + + if(xattr_size < 0) { + goto fail; } + + if(xattr_size == 0) { + RETURN_EMPTY_STRING(); + } + + values = do_alloca(xattr_size + 1, use_heap); + + retsize = smbc_getxattr(state->ctx, url, name, values, sizeof(values)); + + if(retsize < 0) + goto fail; + + RETVAL_STRING(values); + free_alloca(values, use_heap); + return; +fail: hide_password(url, url_len); switch (state->err = errno) { case EINVAL: php_error(E_WARNING, "Couldn't get xattr for %s: library not initialized or incorrect parameter", url); break; From c8e80019dbcc57345ffb0ff3a95e9f635333ba12 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 9 Feb 2022 08:52:50 +0100 Subject: [PATCH 2/2] avoid memory duplication --- smbclient.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/smbclient.c b/smbclient.c index a480957..1600570 100644 --- a/smbclient.c +++ b/smbclient.c @@ -1667,8 +1667,11 @@ PHP_FUNCTION(smbclient_getxattr) zval *zstate; smbc_getxattr_fn smbc_getxattr; php_smbclient_state *state; +#if PHP_MAJOR_VERSION >= 7 + zend_string *svalues = NULL; +#else char *values = NULL; - ALLOCA_FLAG(use_heap) +#endif if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &zstate, &url, &url_len, &name, &name_len) == FAILURE) { return; @@ -1681,24 +1684,36 @@ PHP_FUNCTION(smbclient_getxattr) xattr_size = smbc_getxattr(state->ctx, url, name, NULL, 0); - if(xattr_size < 0) { + if (xattr_size < 0) { goto fail; } - if(xattr_size == 0) { + if (xattr_size == 0) { RETURN_EMPTY_STRING(); } - values = do_alloca(xattr_size + 1, use_heap); - - retsize = smbc_getxattr(state->ctx, url, name, values, sizeof(values)); - - if(retsize < 0) +#if PHP_MAJOR_VERSION >= 7 + svalues = zend_string_alloc(xattr_size, 0); + retsize = smbc_getxattr(state->ctx, url, name, ZSTR_VAL(svalues), xattr_size + 1); + if (retsize > xattr_size) { /* time-of-check, time-of-use error */ + retsize = xattr_size; + } else if (retsize < 0) { + zend_string_release(svalues); goto fail; + } + RETURN_STR(svalues); +#else + values = emalloc(xattr_size + 1); + retsize = smbc_getxattr(state->ctx, url, name, values, xattr_size + 1); + if (retsize > xattr_size) { /* time-of-check, time-of-use error */ + retsize = xattr_size; + } else if (retsize < 0) { + efree(values); + goto fail; + } + RETURN_STRINGL(values, retsize, 0); +#endif - RETVAL_STRING(values); - free_alloca(values, use_heap); - return; fail: hide_password(url, url_len); switch (state->err = errno) {