CVE-2018-8754: Out-of-bounds Read (CWE-125)
value: The libevt_record_values_read_event() function in libevt_record_values.c in libevt before 2018-03-17 does not properly check for out-of-bounds values of user SID data size, strings size, or data size. NOTE: the vendor has disputed this as described in libyal/libevt issue 5 on GitHub
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 5.5
Published: 2018-03-18T03:29Z
Repository: https://github.com/libyal/libevt
Language: Other
Files changed: configure.ac, libevt.nuspec, libevt/libevt_libfvalue.h, libevt/libevt_record_values.c, m4/libcdata.m4, m4/libcsplit.m4, m4/libfdata.m4, runtests.sh
Commit date: 2018-03-17 10:16:45 +0100
Commit message: Applied updates and addition boundary checks for corrupted data

Diff: diff --git a/configure.ac b/configure.ac
index c90de8f..f51519d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,10 +1,10 @@
 AC_PREREQ( 2.59 )
 
 AC_INIT(
  [libevt],
- [20180125],
+ [20180317],
  [joachim.metz@gmail.com])
 
 AC_CONFIG_SRCDIR(
  [include/libevt.h.in])
 
@@ -46,10 +46,16 @@ dnl Check if WINAPI support should be enabled
 AX_COMMON_CHECK_ENABLE_WINAPI
 
 dnl Check if wide character type should be enabled
 AX_COMMON_CHECK_ENABLE_WIDE_CHARACTER_TYPE
 
+dnl Check if verbose output should be enabled
+AX_COMMON_CHECK_ENABLE_VERBOSE_OUTPUT
+
+dnl Check if debug output should be enabled
+AX_COMMON_CHECK_ENABLE_DEBUG_OUTPUT
+
 dnl Check for type definitions
 AX_TYPES_CHECK_LOCAL
 
 dnl Check if common required headers and functions are available
 AX_COMMON_CHECK_LOCAL
@@ -144,16 +150,10 @@ dnl Check if libcdirectory or required headers and functions are available
 AX_LIBCDIRECTORY_CHECK_ENABLE
 
 dnl Check if evttools required headers and functions are available
 AX_EVTTOOLS_CHECK_LOCAL
 
-dnl Check if libevt should be build with verbose output
-AX_COMMON_CHECK_ENABLE_VERBOSE_OUTPUT
-
-dnl Check if libevt should be build with debug output
-AX_COMMON_CHECK_ENABLE_DEBUG_OUTPUT
-
 dnl Check if tests required headers and functions are available
 AX_TESTS_CHECK_LOCAL
 
 dnl Check if DLL support is needed
 AS_IF(
diff --git a/libevt.nuspec b/libevt.nuspec
index 3603086..a390283 100644
--- a/libevt.nuspec
+++ b/libevt.nuspec
@@ -1,18 +1,18 @@
 <?xml version="1.0"?>
 <package >
   <metadata>
     <id>libevt</id>
-    <version>20180125</version>
+    <version>20180317</version>
     <authors>Joachim Metz</authors>
     <owners>joachimmetz</owners>
     <licenseUrl>https://raw.githubusercontent.com/libyal/libevt/master/COPYING</licenseUrl>
     <projectUrl>https://github.com/libyal/libevt</projectUrl>
     <requireLicenseAcceptance>false</requireLicenseAcceptance>
     <title>libevt</title>
     <description>Library to access the Windows Event Log (EVT) format</description>
-    <releaseNotes>Release of libevt 20180125</releaseNotes>
+    <releaseNotes>Release of libevt 20180317</releaseNotes>
     <copyright>Copyright (C) 2011-2018</copyright>
     <tags>native</tags>
   </metadata>
   <files>
     <file src="include\*.h" target="lib\native\include\" />
diff --git a/libevt/libevt_libfvalue.h b/libevt/libevt_libfvalue.h
index fb914f4..4dc9a4e 100644
--- a/libevt/libevt_libfvalue.h
+++ b/libevt/libevt_libfvalue.h
@@ -27,10 +27,11 @@
 /* Define HAVE_LOCAL_LIBFVALUE for local use of libfvalue
  */
 #if defined( HAVE_LOCAL_LIBFVALUE )
 
 #include <libfvalue_codepage.h>
+#include <libfvalue_data_handle.h>
 #include <libfvalue_definitions.h>
 #include <libfvalue_floating_point.h>
 #include <libfvalue_integer.h>
 #include <libfvalue_split_utf16_string.h>
 #include <libfvalue_split_utf8_string.h>
diff --git a/libevt/libevt_record_values.c b/libevt/libevt_record_values.c
index 879dff2..c8f46a3 100644
--- a/libevt/libevt_record_values.c
+++ b/libevt/libevt_record_values.c
@@ -1155,10 +1155,21 @@ int libevt_record_values_read_event(
 			record_data_offset += members_data_size;
 		}
 	}
 	if( user_sid_size != 0 )
 	{
+		if( user_sid_size > ( ( record_data_size - 4 ) - user_sid_offset ) )
+		{
+			libcerror_error_set(
+			 error,
+			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
+			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
+			 "%s: user SID data size value out of bounds.",
+			 function );
+
+			goto on_error;
+		}
 		if( libfvalue_value_type_initialize(
 		     &( record_values->user_security_identifier ),
 		     LIBFVALUE_VALUE_TYPE_NT_SECURITY_IDENTIFIER,
 		     error ) != 1 )
 		{
@@ -1216,10 +1227,21 @@ int libevt_record_values_read_event(
 #endif
 		record_data_offset += user_sid_size;
 	}
 	if( strings_size != 0 )
 	{
+		if( strings_size > ( ( record_data_size - 4 ) - strings_offset ) )
+		{
+			libcerror_error_set(
+			 error,
+			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
+			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
+			 "%s: strings size value out of bounds.",
+			 function );
+
+			goto on_error;
+		}
 #if defined( HAVE_DEBUG_OUTPUT )
 		if( libcnotify_verbose != 0 )
 		{
 			libcnotify_printf(
 			 "%s: strings data:\n",
@@ -1283,18 +1305,29 @@ int libevt_record_values_read_event(
 		}
 		record_data_offset += strings_size;
 	}
 	if( data_size != 0 )
 	{
+		if( data_size > ( ( record_data_size - 4 ) - record_data_offset ) )
+		{
+			libcerror_error_set(
+			 error,
+			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
+			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
+			 "%s: data size value out of bounds.",
+			 function );
+
+			goto on_error;
+		}
 #if defined( HAVE_DEBUG_OUTPUT )
 		if( libcnotify_verbose != 0 )
 		{
 			libcnotify_printf(
 			 "%s: data:\n",
 			 function );
 			libcnotify_print_data(
-			 &( record_data[ data_offset ] ),
+			 &( record_data[ record_data_offset ] ),
 			 (size_t) data_size,
 			 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
 		}
 #endif
 		if( libfvalue_value_type_initialize(
diff --git a/m4/libcdata.m4 b/m4/libcdata.m4
index c19c04f..f4067aa 100644
--- a/m4/libcdata.m4
+++ b/m4/libcdata.m4
@@ -1,8 +1,8 @@
 dnl Checks for libcdata or required headers and functions
 dnl
-dnl Version: 20170904
+dnl Version: 20180316
 
 dnl Function to detect if libcdata is available
 dnl ac_libcdata_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l<library> arguments
 AC_DEFUN([AX_LIBCDATA_CHECK_LIB],
   [dnl Check if parameters were provided
@@ -121,10 +121,52 @@ AC_DEFUN([AX_LIBCDATA_CHECK_LIB],
           cdata,
           libcdata_array_remove_entry,
           [ac_cv_libcdata_dummy=yes],
           [ac_cv_libcdata=no])
 
+        dnl Balanced tree functions
+        AC_CHECK_LIB(
+          cdata,
+          libfdata_btree_initialize,
+          [ac_cv_libcdata_dummy=yes],
+          [ac_cv_libcdata=no])
+        AC_CHECK_LIB(
+          cdata,
+          libcdata_btree_free,
+          [ac_cv_libcdata_dummy=yes],
+          [ac_cv_libcdata=no])
+        AC_CHECK_LIB(
+          cdata,
+          libcdata_btree_get_number_of_values,
+          [ac_cv_libcdata_dummy=yes],
+          [ac_cv_libcdata=no])
+        AC_CHECK_LIB(
+          cdata,
+          libcdata_btree_get_value_by_index,
+          [ac_cv_libcdata_dummy=yes],
+          [ac_cv_libcdata=no])
+        AC_CHECK_LIB(
+          cdata,
+          libcdata_btree_get_value_by_value,
+          [ac_cv_libcdata_dummy=yes],
+          [ac_cv_libcdata=no])
+        AC_CHECK_LIB(
+          cdata,
+          libcdata_btree_insert_value,
+          [ac_cv_libcdata_dummy=yes],
+          [ac_cv_libcdata=no])
+        AC_CHECK_LIB(
+          cdata,
+          libcdata_btree_replace_value,
+          [ac_cv_libcdata_dummy=yes],
+          [ac_cv_libcdata=no])
+        AC_CHECK_LIB(
+          cdata,
+          libcdata_btree_remove_value,
+          [ac_cv_libcdata_dummy=yes],
+          [ac_cv_libcdata=no])
+
         dnl List functions
         AC_CHECK_LIB(
           cdata,
           libcdata_list_initialize,
           [ac_cv_libcdata_dummy=yes],
diff --git a/m4/libcsplit.m4 b/m4/libcsplit.m4
index f49d839..c911016 100644
--- a/m4/libcsplit.m4
+++ b/m4/libcsplit.m4
@@ -1,8 +1,8 @@
 dnl Checks for libcsplit or required headers and functions
 dnl
-dnl Version: 20170903
+dnl Version: 20180217
 
 dnl Function to detect if libcsplit is available
 dnl ac_libcsplit_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l<library> arguments
 AC_DEFUN([AX_LIBCSPLIT_CHECK_LIB],
   [dnl Check if parameters were provided
@@ -109,11 +109,11 @@ AC_DEFUN([AX_LIBCSPLIT_CHECK_LIB],
 
         dnl Wide string functions
         AS_IF(
           [test "x$ac_cv_enable_wide_character_type" != xno],
           [AC_CHECK_LIB(
-          csplit,
+            csplit,
             libcsplit_wide_string_split,
             [ac_cv_libcsplit_dummy=yes],
             [ac_cv_libcsplit=no])
 
         dnl Wide split string functions
diff --git a/m4/libfdata.m4 b/m4/libfdata.m4
index 3e7670d..6dfec55 100644
--- a/m4/libfdata.m4
+++ b/m4/libfdata.m4
@@ -1,8 +1,8 @@
 dnl Functions for libfdata
 dnl
-dnl Version: 20170905
+dnl Version: 20180316
 
 dnl Function to detect if libfdata is available
 dnl ac_libfdata_dummy is used to prevent AC_CHECK_LIB adding unnecessary -l<library> arguments
 AC_DEFUN([AX_LIBFDATA_CHECK_LIB],
   [dnl Check if parameters were provided
@@ -47,11 +47,80 @@ AC_DEFUN([AX_LIBFDATA_CHECK_LIB],
           libfdata_get_version,
           [ac_cv_libfdata_dummy=yes],
           [ac_cv_libfdata=no])
 
         dnl Area functions
-        dnl TODO: add functions
+        AC_CHECK_LIB(
+          fdata,
+          libfdata_area_initialize,
+          [ac_cv_libfdata_dummy=yes],
+          [ac_cv_libfdata=no])
+        AC_CHECK_LIB(
+          fdata,
+          libfdata_area_free,
+          [ac_cv_libfdata_dummy=yes],
+          [ac_cv_libfdata=no])
+        AC_CHECK_LIB(
+          fdata,
+          libfdata_area_clone,
+          [ac_cv_libfdata_dummy=yes],
+          [ac_cv_libfdata=no])
+        AC_CHECK_LIB(
+          fdata,
+          libfdata_area_empty,
+          [ac_cv_libfdata_dummy=yes],
+          [ac_cv_libfdata=no])
+        AC_CHECK_LIB(
+          fdata,
+          libfdata_area_resize,
+          [ac_cv_libfdata_dummy=yes],
+          [ac_cv_libfdata=no])
+        AC_CHECK_LIB(
+          fdata,
+          libfdata_area_get_number_of_segments,
+          [ac_cv_libfdata_dummy=yes],
+          [ac_cv_libfdata=no])
+        AC_CHECK_LIB(
+          fdata,
+          libfdata_area_get_segment_by_index,
+          [ac_cv_libfdata_dummy=yes],
+          [ac_cv_libfdata=no])
+        AC_CHECK_LIB(
+          fdata,
+          libfdata_area_set_segment_by_index,
+          [ac_cv_libfdata_dummy=yes],
+          [ac_cv_libfdata=no])
+        AC_CHECK_LIB(
+          fdata,
+          libfdata_area_prepend_segment,
+          [ac_cv_libfdata_dummy=yes],
+          [ac_cv_libfdata=no])
+        AC_CHECK_LIB(
+          fdata,
+          libfdata_area_append_segment,
+          [ac_cv_libfdata_dummy=yes],
+          [ac_cv_libfdata=no])
+        AC_CHECK_LIB(
+          fdata,
+          libfdata_area_get_element_data_size,
+          [ac_cv_libfdata_dummy=yes],
+          [ac_cv_libfdata=no])
+        AC_CHECK_LIB(
+          fdata,
+          libfdata_area_get_element_value_at_offset,
+          [ac_cv_libfdata_dummy=yes],
+          [ac_cv_libfdata=no])
+        AC_CHECK_LIB(
+          fdata,
+          libfdata_area_set_element_value_at_offset,
+          [ac_cv_libfdata_dummy=yes],
+          [ac_cv_libfdata=no])
+        AC_CHECK_LIB(
+          fdata,
+          libfdata_area_get_size,
+          [ac_cv_libfdata_dummy=yes],
+          [ac_cv_libfdata=no])
 
         dnl Balanced tree functions
         dnl TODO: add functions
 
         dnl List functions
diff --git a/runtests.sh b/runtests.sh
index 49c7d09..0ef7640 100755
--- a/runtests.sh
+++ b/runtests.sh
@@ -1,9 +1,9 @@
 #!/bin/bash
 # Script that runs the tests
 #
-# Version: 20171210
+# Version: 20180214
 
 EXIT_SUCCESS=0;
 EXIT_FAILURE=1;
 
 run_configure_make()
@@ -199,10 +199,18 @@ CONFIGURE_HELP=`./configure --help`;
 
 echo "${CONFIGURE_HELP}" | grep -- '--enable-wide-character-type' > /dev/null;
 
 HAVE_ENABLE_WIDE_CHARACTER_TYPE=$?;
 
+echo "${CONFIGURE_HELP}" | grep -- '--enable-verbose-output' > /dev/null;
+
+HAVE_ENABLE_VERBOSE_OUTPUT=$?;
+
+echo "${CONFIGURE_HELP}" | grep -- '--enable-debug-output' > /dev/null;
+
+HAVE_ENABLE_DEBUG_OUTPUT=$?;
+
 echo "${CONFIGURE_HELP}" | grep -- '--with-zlib' > /dev/null;
 
 HAVE_WITH_ZLIB=$?;
 
 echo "${CONFIGURE_HELP}" | grep -- '--with-openssl' > /dev/null;
@@ -228,10 +236,23 @@ RESULT=$?;
 if test ${RESULT} -ne ${EXIT_SUCCESS};
 then
 	exit ${EXIT_FAILURE};
 fi
 
+if test ${HAVE_ENABLE_VERBOSE_OUTPUT} -eq 0 && test ${HAVE_ENABLE_DEBUG_OUTPUT} -eq 0;
+then
+	# Test "./configure && make && make check" with verbose and debug output.
+
+	run_configure_make_check "--enable-verbose-output --enable-debug-output";
+	RESULT=$?;
+
+	if test ${RESULT} -ne ${EXIT_SUCCESS};
+	then
+		exit ${EXIT_FAILURE};
+	fi
+fi
+
 if test ${HAVE_WITH_ZLIB} -eq 0;
 then
 	# Test "./configure && make && make check" with fallback zlib implementation.
 
 	run_configure_make_check "--with-zlib=no";

Vulnerable code:  [20180125],
dnl Check if libevt should be build with verbose output
AX_COMMON_CHECK_ENABLE_VERBOSE_OUTPUT

dnl Check if libevt should be build with debug output
AX_COMMON_CHECK_ENABLE_DEBUG_OUTPUT

    <version>20180125</version>
    <releaseNotes>Release of libevt 20180125</releaseNotes>
			 &( record_data[ data_offset ] ),
dnl Version: 20170904
dnl Version: 20170903
          csplit,
dnl Version: 20170905
        dnl TODO: add functions
# Version: 20171210
Fixed code:  [20180317],
dnl Check if verbose output should be enabled
AX_COMMON_CHECK_ENABLE_VERBOSE_OUTPUT

dnl Check if debug output should be enabled
AX_COMMON_CHECK_ENABLE_DEBUG_OUTPUT

    <version>20180317</version>
    <releaseNotes>Release of libevt 20180317</releaseNotes>
#include <libfvalue_data_handle.h>
		if( user_sid_size > ( ( record_data_size - 4 ) - user_sid_offset ) )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
			 "%s: user SID data size value out of bounds.",
			 function );

			goto on_error;
		}
		if( strings_size > ( ( record_data_size - 4 ) - strings_offset ) )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
			 "%s: strings size value out of bounds.",
			 function );

			goto on_error;
		}
		if( data_size > ( ( record_data_size - 4 ) - record_data_offset ) )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
			 "%s: data size value out of bounds.",
			 function );

			goto on_error;
		}
			 &( record_data[ record_data_offset ] ),
dnl Version: 20180316
        dnl Balanced tree functions
        AC_CHECK_LIB(
          cdata,
          libfdata_btree_initialize,
          [ac_cv_libcdata_dummy=yes],
          [ac_cv_libcdata=no])
        AC_CHECK_LIB(
          cdata,
          libcdata_btree_free,
          [ac_cv_libcdata_dummy=yes],
          [ac_cv_libcdata=no])
        AC_CHECK_LIB(
          cdata,
          libcdata_btree_get_number_of_values,
          [ac_cv_libcdata_dummy=yes],
          [ac_cv_libcdata=no])
        AC_CHECK_LIB(
          cdata,
          libcdata_btree_get_value_by_index,
          [ac_cv_libcdata_dummy=yes],
          [ac_cv_libcdata=no])
        AC_CHECK_LIB(
          cdata,
          libcdata_btree_get_value_by_value,
          [ac_cv_libcdata_dummy=yes],
          [ac_cv_libcdata=no])
        AC_CHECK_LIB(
          cdata,
          libcdata_btree_insert_value,
          [ac_cv_libcdata_dummy=yes],
          [ac_cv_libcdata=no])
        AC_CHECK_LIB(
          cdata,
          libcdata_btree_replace_value,
          [ac_cv_libcdata_dummy=yes],
          [ac_cv_libcdata=no])
        AC_CHECK_LIB(
          cdata,
          libcdata_btree_remove_value,
          [ac_cv_libcdata_dummy=yes],
          [ac_cv_libcdata=no])

dnl Version: 20180217
            csplit,
dnl Version: 20180316
        AC_CHECK_LIB(
          fdata,
          libfdata_area_initialize,
          [ac_cv_libfdata_dummy=yes],
          [ac_cv_libfdata=no])
        AC_CHECK_LIB(
          fdata,
          libfdata_area_free,
          [ac_cv_libfdata_dummy=yes],
          [ac_cv_libfdata=no])
        AC_CHECK_LIB(
          fdata,
          libfdata_area_clone,
          [ac_cv_libfdata_dummy=yes],
          [ac_cv_libfdata=no])
        AC_CHECK_LIB(
          fdata,
          libfdata_area_empty,
          [ac_cv_libfdata_dummy=yes],
          [ac_cv_libfdata=no])
        AC_CHECK_LIB(
          fdata,
          libfdata_area_resize,
          [ac_cv_libfdata_dummy=yes],
          [ac_cv_libfdata=no])
        AC_CHECK_LIB(
          fdata,
          libfdata_area_get_number_of_segments,
          [ac_cv_libfdata_dummy=yes],
          [ac_cv_libfdata=no])
        AC_CHECK_LIB(
          fdata,
          libfdata_area_get_segment_by_index,
          [ac_cv_libfdata_dummy=yes],
          [ac_cv_libfdata=no])
        AC_CHECK_LIB(
          fdata,
          libfdata_area_set_segment_by_index,
          [ac_cv_libfdata_dummy=yes],
          [ac_cv_libfdata=no])
        AC_CHECK_LIB(
          fdata,
          libfdata_area_prepend_segment,
          [ac_cv_libfdata_dummy=yes],
          [ac_cv_libfdata=no])
        AC_CHECK_LIB(
          fdata,
          libfdata_area_append_segment,
          [ac_cv_libfdata_dummy=yes],
          [ac_cv_libfdata=no])
        AC_CHECK_LIB(
          fdata,
          libfdata_area_get_element_data_size,
          [ac_cv_libfdata_dummy=yes],
          [ac_cv_libfdata=no])
        AC_CHECK_LIB(
          fdata,
          libfdata_area_get_element_value_at_offset,
          [ac_cv_libfdata_dummy=yes],
          [ac_cv_libfdata=no])
        AC_CHECK_LIB(
          fdata,
          libfdata_area_set_element_value_at_offset,
          [ac_cv_libfdata_dummy=yes],
          [ac_cv_libfdata=no])
        AC_CHECK_LIB(
          fdata,
          libfdata_area_get_size,
          [ac_cv_libfdata_dummy=yes],
          [ac_cv_libfdata=no])
# Version: 20180214
echo "${CONFIGURE_HELP}" | grep -- '--enable-verbose-output' > /dev/null;

HAVE_ENABLE_VERBOSE_OUTPUT=$?;

echo "${CONFIGURE_HELP}" | grep -- '--enable-debug-output' > /dev/null;

HAVE_ENABLE_DEBUG_OUTPUT=$?;

if test ${HAVE_ENABLE_VERBOSE_OUTPUT} -eq 0 && test ${HAVE_ENABLE_DEBUG_OUTPUT} -eq 0;
then
	# Test "./configure && make && make check" with verbose and debug output.

	run_configure_make_check "--enable-verbose-output --enable-debug-output";
	RESULT=$?;

	if test ${RESULT} -ne ${EXIT_SUCCESS};
	then
		exit ${EXIT_FAILURE};
	fi
fi