Fix 1-byte buffer overwrites due to null-termination
Add axutil_stream_set_buffer_end_null function to allow memory
reallocation if needed when null-terminating a basic stream.
Fixes: AXIS2C-1600
diff --git a/axiom/src/om/om_data_source.c b/axiom/src/om/om_data_source.c
index 3959e49..4f6db77 100644
--- a/axiom/src/om/om_data_source.c
+++ b/axiom/src/om/om_data_source.c
@@ -108,16 +108,14 @@
{
int status = AXIS2_SUCCESS;
axis2_char_t *data = NULL;
- unsigned int data_len = 0;
AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
AXIS2_PARAM_CHECK(env->error, om_output, AXIS2_FAILURE);
+ axutil_stream_set_buffer_end_null(data_source->stream, env);
data = axutil_stream_get_buffer(data_source->stream, env);
- data_len = axutil_stream_get_len(data_source->stream, env);
if(data)
{
- data[data_len] = '\0';
status = axiom_output_write(om_output, env, AXIOM_DATA_SOURCE, 1, data);
}
return status;
diff --git a/src/core/transport/http/common/simple_http_svr_conn.c b/src/core/transport/http/common/simple_http_svr_conn.c
index 958be28..4aa71e6 100644
--- a/src/core/transport/http/common/simple_http_svr_conn.c
+++ b/src/core/transport/http/common/simple_http_svr_conn.c
@@ -282,9 +282,9 @@
if(response_stream)
{
body_size = axutil_stream_get_len(response_stream, env);
+ axutil_stream_set_buffer_end_null(response_stream, env);
response_body = axutil_stream_get_buffer(response_stream, env);
axutil_stream_flush_buffer(response_stream, env);
- response_body[body_size] = AXIS2_ESC_NULL;
}
if(body_size <= 0 && !binary_content)
diff --git a/test/core/transport/http/test_http_transport.cc b/test/core/transport/http/test_http_transport.cc
index 86d1b2f..17ee4a0 100644
--- a/test/core/transport/http/test_http_transport.cc
+++ b/test/core/transport/http/test_http_transport.cc
@@ -32,6 +32,7 @@
#include <axis2_json_writer.h>
#include <axis2_json_reader.h>
#endif
+#include <axis2_simple_http_svr_conn.h>
#include "../../../cutest/include/cut_http_server.h"
@@ -450,3 +451,23 @@
}
#endif
+
+TEST_F(TestHTTPTransport, test_AXIS2C_1600)
+{
+ axis2_simple_http_svr_conn_t* conn = axis2_simple_http_svr_conn_create(
+ m_env, -1);
+
+ axis2_http_simple_response_t* resp = axis2_http_simple_response_create(
+ m_env, NULL, NULL, 0, NULL);
+ axis2_char_t body[AXIS2_STREAM_DEFAULT_BUF_SIZE+1];
+ memset(body, 'A', AXIS2_STREAM_DEFAULT_BUF_SIZE+1);
+ body[AXIS2_STREAM_DEFAULT_BUF_SIZE] = '\0';
+
+ axis2_http_simple_response_set_status_line(resp, m_env, "1.1", 200, "OK");
+ axis2_http_simple_response_set_body_string(resp, m_env, body);
+
+ axis2_simple_http_svr_conn_write_response(conn, m_env, resp);
+
+ axis2_http_simple_response_free(resp, m_env);
+ axis2_simple_http_svr_conn_free(conn, m_env);
+}
diff --git a/util/include/axutil_stream.h b/util/include/axutil_stream.h
index a506811..92c9c17 100644
--- a/util/include/axutil_stream.h
+++ b/util/include/axutil_stream.h
@@ -283,6 +283,16 @@
const axutil_stream_t * stream,
const axutil_env_t * env);
+ /**
+ * Appends a null terminator to the buffer, allocating additional memory
+ * if necessary.
+ * @return Length of the buffer plus null terminator, or -1 on error
+ */
+ AXIS2_EXTERN int AXIS2_CALL
+ axutil_stream_set_buffer_end_null(
+ axutil_stream_t *stream,
+ axutil_env_t *env);
+
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_stream_flush_buffer(
axutil_stream_t * stream,
diff --git a/util/src/stream.c b/util/src/stream.c
index bdc4e03..8f3d986 100644
--- a/util/src/stream.c
+++ b/util/src/stream.c
@@ -377,6 +377,33 @@
return stream->buffer;
}
+AXIS2_EXTERN int AXIS2_CALL
+axutil_stream_set_buffer_end_null(
+ axutil_stream_t *stream,
+ axutil_env_t *env)
+{
+ if (!stream || !env) return -1;
+
+ if (stream->len + 1 >= stream->max_len) {
+
+ axis2_char_t *tmp = (axis2_char_t *)AXIS2_MALLOC(env->allocator,
+ sizeof(axis2_char_t) * (stream->len + 1));
+ if(!tmp)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ return -1;
+ }
+ stream->max_len = stream->len + 1;
+ memcpy(tmp, stream->buffer_head, sizeof(axis2_char_t) * stream->len);
+ AXIS2_FREE(env->allocator, stream->buffer_head);
+ stream->buffer = tmp;
+ stream->buffer_head = tmp;
+ }
+ *(stream->buffer_head + stream->len) = '\0';
+ return stream->len + 1;
+
+}
+
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_stream_flush_buffer(
axutil_stream_t *stream,