Add input validation to SDL_getenv/SDL_setenv; update Stdlib testsuite; add Hints testsuite
authorAndreas Schiffler <aschiffler@ferzkopp.net>
Wed, 19 Mar 2014 21:39:55 -0700
changeset 8645 d69fdbefeecf
parent 8644 f218b4e65498
child 8646 0a20fff4de3c
Add input validation to SDL_getenv/SDL_setenv; update Stdlib testsuite; add Hints testsuite
VisualC/tests/testautomation/testautomation_VS2008.vcproj
VisualC/tests/testautomation/testautomation_vs2010.vcxproj
VisualC/tests/testautomation/testautomation_vs2012.vcxproj
VisualC/tests/testautomation/testautomation_vs2013.vcxproj
src/stdlib/SDL_getenv.c
test/Makefile.in
test/testautomation_hints.c
test/testautomation_stdlib.c
test/testautomation_suites.h
--- a/VisualC/tests/testautomation/testautomation_VS2008.vcproj	Wed Mar 19 22:43:30 2014 -0400
+++ b/VisualC/tests/testautomation/testautomation_VS2008.vcproj	Wed Mar 19 21:39:55 2014 -0700
@@ -271,6 +271,10 @@
 			RelativePath="..\..\..\test\testautomation_video.c"
 			>
 		</File>
+		<File
+			RelativePath="..\..\..\test\testautomation_hints.c"
+			>
+		</File>
 	</Files>
 	<Globals>
 	</Globals>
--- a/VisualC/tests/testautomation/testautomation_vs2010.vcxproj	Wed Mar 19 22:43:30 2014 -0400
+++ b/VisualC/tests/testautomation/testautomation_vs2010.vcxproj	Wed Mar 19 21:39:55 2014 -0700
@@ -194,6 +194,7 @@
     <ClCompile Include="..\..\..\test\testautomation_syswm.c" />
     <ClCompile Include="..\..\..\test\testautomation_timer.c" />
     <ClCompile Include="..\..\..\test\testautomation_video.c" />
+    <ClCompile Include="..\..\..\test\testautomation_hints.c" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\test\testautomation_suites.h" />
--- a/VisualC/tests/testautomation/testautomation_vs2012.vcxproj	Wed Mar 19 22:43:30 2014 -0400
+++ b/VisualC/tests/testautomation/testautomation_vs2012.vcxproj	Wed Mar 19 21:39:55 2014 -0700
@@ -198,6 +198,7 @@
     <ClCompile Include="..\..\..\test\testautomation_syswm.c" />
     <ClCompile Include="..\..\..\test\testautomation_timer.c" />
     <ClCompile Include="..\..\..\test\testautomation_video.c" />
+    <ClCompile Include="..\..\..\test\testautomation_hints.c" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\test\testautomation_suites.h" />
--- a/VisualC/tests/testautomation/testautomation_vs2013.vcxproj	Wed Mar 19 22:43:30 2014 -0400
+++ b/VisualC/tests/testautomation/testautomation_vs2013.vcxproj	Wed Mar 19 21:39:55 2014 -0700
@@ -198,6 +198,7 @@
     <ClCompile Include="..\..\..\test\testautomation_syswm.c" />
     <ClCompile Include="..\..\..\test\testautomation_timer.c" />
     <ClCompile Include="..\..\..\test\testautomation_video.c" />
+    <ClCompile Include="..\..\..\test\testautomation_hints.c" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\test\testautomation_suites.h" />
--- a/src/stdlib/SDL_getenv.c	Wed Mar 19 22:43:30 2014 -0400
+++ b/src/stdlib/SDL_getenv.c	Wed Mar 19 21:39:55 2014 -0700
@@ -33,16 +33,27 @@
 #endif
 
 /* Put a variable into the environment */
+/* Note: Name may not contain a '=' character. (Reference: http://www.unix.com/man-page/Linux/3/setenv/) */
 #if defined(HAVE_SETENV)
 int
 SDL_setenv(const char *name, const char *value, int overwrite)
 {
+    /* Input validation */
+    if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
+        return (-1);
+    }
+    
     return setenv(name, value, overwrite);
 }
 #elif defined(__WIN32__)
 int
 SDL_setenv(const char *name, const char *value, int overwrite)
 {
+    /* Input validation */
+    if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
+        return (-1);
+    }
+    
     if (!overwrite) {
         char ch = 0;
         const size_t len = GetEnvironmentVariableA(name, &ch, sizeof (ch));
@@ -63,6 +74,11 @@
     size_t len;
     char *new_variable;
 
+    /* Input validation */
+    if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
+        return (-1);
+    }
+    
     if (getenv(name) != NULL) {
         if (overwrite) {
             unsetenv(name);
@@ -91,8 +107,8 @@
     char **new_env;
     char *new_variable;
 
-    /* A little error checking */
-    if (!name || !value) {
+    /* Input validation */
+    if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
         return (-1);
     }
 
@@ -152,6 +168,11 @@
 char *
 SDL_getenv(const char *name)
 {
+    /* Input validation */
+    if (!name || SDL_strlen(name)==0) {
+        return NULL;
+    }
+
     return getenv(name);
 }
 #elif defined(__WIN32__)
@@ -160,6 +181,11 @@
 {
     size_t bufferlen;
 
+    /* Input validation */
+    if (!name || SDL_strlen(name)==0) {
+        return NULL;
+    }
+    
     bufferlen =
         GetEnvironmentVariableA(name, SDL_envmem, (DWORD) SDL_envmemlen);
     if (bufferlen == 0) {
@@ -183,6 +209,11 @@
     int len, i;
     char *value;
 
+    /* Input validation */
+    if (!name || SDL_strlen(name)==0) {
+        return NULL;
+    }
+    
     value = (char *) 0;
     if (SDL_env) {
         len = SDL_strlen(name);
--- a/test/Makefile.in	Wed Mar 19 22:43:30 2014 -0400
+++ b/test/Makefile.in	Wed Mar 19 21:39:55 2014 -0700
@@ -92,7 +92,8 @@
 		      $(srcdir)/testautomation_surface.c \
 		      $(srcdir)/testautomation_syswm.c \
 		      $(srcdir)/testautomation_timer.c \
-		      $(srcdir)/testautomation_video.c
+		      $(srcdir)/testautomation_video.c \
+		      $(srcdir)/testautomation_hints.c
 	$(CC) -o $@ $^ $(CFLAGS) $(LIBS) 
 
 testmultiaudio$(EXE): $(srcdir)/testmultiaudio.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testautomation_hints.c	Wed Mar 19 21:39:55 2014 -0700
@@ -0,0 +1,168 @@
+/**
+ * Hints test suite
+ */
+
+#include <stdio.h>
+
+#include "SDL.h"
+#include "SDL_test.h"
+
+
+const int _numHintsEnum = 25;
+char* _HintsEnum[] =
+  {
+    SDL_HINT_ACCELEROMETER_AS_JOYSTICK,
+    SDL_HINT_FRAMEBUFFER_ACCELERATION,
+    SDL_HINT_GAMECONTROLLERCONFIG,
+    SDL_HINT_GRAB_KEYBOARD,
+    SDL_HINT_IDLE_TIMER_DISABLED,
+    SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
+    SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK,
+    SDL_HINT_MOUSE_RELATIVE_MODE_WARP,
+    SDL_HINT_ORIENTATIONS,
+    SDL_HINT_RENDER_DIRECT3D_THREADSAFE,
+    SDL_HINT_RENDER_DRIVER,
+    SDL_HINT_RENDER_OPENGL_SHADERS,
+    SDL_HINT_RENDER_SCALE_QUALITY,
+    SDL_HINT_RENDER_VSYNC,
+    SDL_HINT_TIMER_RESOLUTION,
+    SDL_HINT_VIDEO_ALLOW_SCREENSAVER,
+    SDL_HINT_VIDEO_HIGHDPI_DISABLED,
+    SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES,
+    SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS,
+    SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT,
+    SDL_HINT_VIDEO_WIN_D3DCOMPILER,
+    SDL_HINT_VIDEO_X11_XINERAMA,
+    SDL_HINT_VIDEO_X11_XRANDR,
+    SDL_HINT_VIDEO_X11_XVIDMODE,
+    SDL_HINT_XINPUT_ENABLED,
+  };
+char* _HintsVerbose[] =
+  {
+    "SDL_HINT_ACCELEROMETER_AS_JOYSTICK",
+    "SDL_HINT_FRAMEBUFFER_ACCELERATION",
+    "SDL_HINT_GAMECONTROLLERCONFIG",
+    "SDL_HINT_GRAB_KEYBOARD",
+    "SDL_HINT_IDLE_TIMER_DISABLED",
+    "SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS",
+    "SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK",
+    "SDL_HINT_MOUSE_RELATIVE_MODE_WARP",
+    "SDL_HINT_ORIENTATIONS",
+    "SDL_HINT_RENDER_DIRECT3D_THREADSAFE",
+    "SDL_HINT_RENDER_DRIVER",
+    "SDL_HINT_RENDER_OPENGL_SHADERS",
+    "SDL_HINT_RENDER_SCALE_QUALITY",
+    "SDL_HINT_RENDER_VSYNC",
+    "SDL_HINT_TIMER_RESOLUTION",
+    "SDL_HINT_VIDEO_ALLOW_SCREENSAVER",
+    "SDL_HINT_VIDEO_HIGHDPI_DISABLED",
+    "SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES",
+    "SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS",
+    "SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT",
+    "SDL_HINT_VIDEO_WIN_D3DCOMPILER",
+    "SDL_HINT_VIDEO_X11_XINERAMA",
+    "SDL_HINT_VIDEO_X11_XRANDR",
+    "SDL_HINT_VIDEO_X11_XVIDMODE",
+    "SDL_HINT_XINPUT_ENABLED"
+  };
+
+
+/* Test case functions */
+
+/**
+ * @brief Call to SDL_GetHint
+ */
+int
+hints_getHint(void *arg)
+{
+  char *result1;
+  char *result2;
+  int i;
+    
+  for (i=0; i<_numHintsEnum; i++) {
+    result1 = (char *)SDL_GetHint((char*)_HintsEnum[i]);
+    SDLTest_AssertPass("Call to SDL_GetHint(%s) - using define definition", (char*)_HintsEnum[i]);
+    result2 = (char *)SDL_GetHint((char *)_HintsVerbose[i]);
+    SDLTest_AssertPass("Call to SDL_GetHint(%s) - using string definition", (char*)_HintsVerbose[i]);
+    SDLTest_AssertCheck(
+      (result1 == NULL && result2 == NULL) || (SDL_strcmp(result1, result2) == 0),
+      "Verify returned values are equal; got: result1='%s' result2='%s",
+      (result1 == NULL) ? "null" : result1,
+      (result2 == NULL) ? "null" : result2);
+  }
+  
+  return TEST_COMPLETED;
+}
+
+/**
+ * @brief Call to SDL_SetHint
+ */
+int
+hints_setHint(void *arg)
+{
+  char *originalValue;
+  char *value;
+  char *testValue;
+  SDL_bool result;
+  int i, j;
+
+  /* Create random values to set */                    
+  value = SDLTest_RandomAsciiStringOfSize(10);
+    
+  for (i=0; i<_numHintsEnum; i++) {
+    /* Capture current value */
+    originalValue = (char *)SDL_GetHint((char*)_HintsEnum[i]);
+    SDLTest_AssertPass("Call to SDL_GetHint(%s)", (char*)_HintsEnum[i]);
+    
+    /* Set value (twice) */
+    for (j=1; j<=2; j++) {
+      result = SDL_SetHint((char*)_HintsEnum[i], value);
+      SDLTest_AssertPass("Call to SDL_SetHint(%s, %s) (iteration %i)", (char*)_HintsEnum[i], value, j);
+      SDLTest_AssertCheck(
+        result == SDL_TRUE || result == SDL_FALSE, 
+        "Verify valid result was returned, got: %i",
+        (int)result);
+      testValue = (char *)SDL_GetHint((char*)_HintsEnum[i]);
+      SDLTest_AssertPass("Call to SDL_GetHint(%s) - using string definition", (char*)_HintsVerbose[i]);
+      SDLTest_AssertCheck(
+        (SDL_strcmp(value, testValue) == 0),
+        "Verify returned value equals set value; got: testValue='%s' value='%s",
+        (testValue == NULL) ? "null" : testValue,
+        value);
+    }
+      
+    /* Reset original value */
+    result = SDL_SetHint((char*)_HintsEnum[i], originalValue);
+    SDLTest_AssertPass("Call to SDL_SetHint(%s, originalValue)", (char*)_HintsEnum[i]);
+    SDLTest_AssertCheck(
+      result == SDL_TRUE || result == SDL_FALSE, 
+      "Verify valid result was returned, got: %i",
+      (int)result);
+  }
+  
+  SDL_free(value);
+  
+  return TEST_COMPLETED;
+}
+
+/* ================= Test References ================== */
+
+/* Hints test cases */
+static const SDLTest_TestCaseReference hintsTest1 =
+        { (SDLTest_TestCaseFp)hints_getHint, "hints_getHint", "Call to SDL_GetHint", TEST_ENABLED };
+
+static const SDLTest_TestCaseReference hintsTest2 =
+        { (SDLTest_TestCaseFp)hints_setHint, "hints_setHint", "Call to SDL_SetHint", TEST_ENABLED };
+
+/* Sequence of Hints test cases */
+static const SDLTest_TestCaseReference *hintsTests[] =  {
+    &hintsTest1, &hintsTest2, NULL
+};
+
+/* Hints test suite (global) */
+SDLTest_TestSuiteReference hintsTestSuite = {
+    "Hints",
+    NULL,
+    hintsTests,
+    NULL
+};
--- a/test/testautomation_stdlib.c	Wed Mar 19 22:43:30 2014 -0400
+++ b/test/testautomation_stdlib.c	Wed Mar 19 21:39:55 2014 -0700
@@ -119,6 +119,140 @@
   return TEST_COMPLETED;
 }
 
+/**
+ * @brief Call to SDL_getenv and SDL_setenv
+ */
+int
+stdlib_getsetenv(void *arg)
+{
+  const int nameLen = 16;
+  int counter;
+  int result;
+  char name[nameLen + 1];
+  char * value1;
+  char * value2;
+  char * expected;
+  int overwrite;
+  char * text;
+
+  /* Create a random name. This tests SDL_getenv, since we need to */
+  /* make sure the variable is not set yet (it shouldn't). */
+  do {
+    for(counter = 0; counter < nameLen; counter++) {
+      name[counter] = (char)SDLTest_RandomIntegerInRange(65, 90);
+    }
+    name[nameLen] = '\0';
+    
+    text = SDL_getenv(name);
+    SDLTest_AssertPass("Call to SDL_getenv('%s')", name);
+    if (text != NULL) {
+      SDLTest_Log("Expected: NULL, Got: '%s' (%i)", text, SDL_strlen(text));
+    }
+  } while (text != NULL);
+   
+  /* Create random values to set */                    
+  value1 = SDLTest_RandomAsciiStringOfSize(10);
+  value2 = SDLTest_RandomAsciiStringOfSize(10);
+
+  /* Set value 1 without overwrite */
+  overwrite = 0;
+  expected = value1;
+  result = SDL_setenv(name, value1, overwrite);
+  SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value1, overwrite);
+  SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result);
+
+  /* Check value */
+  text = SDL_getenv(name);
+  SDLTest_AssertPass("Call to SDL_getenv('%s')", name);
+  SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL");
+  if (text != NULL) {
+    SDLTest_AssertCheck(
+      SDL_strcmp(text, expected) == 0, 
+      "Verify returned text, expected: %s, got: %s",
+      expected,
+      text);
+  }
+  
+  /* Set value 2 with overwrite */
+  overwrite = 1;
+  expected = value2;    
+  result = SDL_setenv(name, value2, overwrite);
+  SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value2, overwrite);
+  SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result);
+
+  /* Check value */
+  text = SDL_getenv(name);
+  SDLTest_AssertPass("Call to SDL_getenv('%s')", name);
+  SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL");
+  if (text != NULL) {
+    SDLTest_AssertCheck(
+      SDL_strcmp(text, expected) == 0, 
+      "Verify returned text, expected: %s, got: %s",
+      expected,
+      text);
+  }
+
+  /* Set value 1 without overwrite */
+  overwrite = 0;
+  expected = value2;    
+  result = SDL_setenv(name, value1, overwrite);
+  SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value1, overwrite);
+  SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result);
+
+  /* Check value */
+  text = SDL_getenv(name);
+  SDLTest_AssertPass("Call to SDL_getenv('%s')", name);
+  SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL");
+  if (text != NULL) {
+    SDLTest_AssertCheck(
+      SDL_strcmp(text, expected) == 0, 
+      "Verify returned text, expected: %s, got: %s",
+      expected,
+      text);
+  }
+  
+  /* Set value 1 without overwrite */
+  overwrite = 1;
+  expected = value1;
+  result = SDL_setenv(name, value1, overwrite);
+  SDLTest_AssertPass("Call to SDL_setenv('%s','%s', %i)", name, value1, overwrite);
+  SDLTest_AssertCheck(result == 0, "Check result, expected: 0, got: %i", result);
+
+  /* Check value */
+  text = SDL_getenv(name);
+  SDLTest_AssertPass("Call to SDL_getenv('%s')", name);
+  SDLTest_AssertCheck(text != NULL, "Verify returned text is not NULL");
+  if (text != NULL) {
+    SDLTest_AssertCheck(
+      SDL_strcmp(text, expected) == 0, 
+      "Verify returned text, expected: %s, got: %s",
+      expected,
+      text);
+  }
+
+  /* Negative cases */
+  for (overwrite=0; overwrite <= 1; overwrite++) { 
+    result = SDL_setenv(NULL, value1, overwrite);
+    SDLTest_AssertPass("Call to SDL_setenv(NULL,'%s', %i)", value1, overwrite);
+    SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result);
+    result = SDL_setenv("", value1, overwrite);
+    SDLTest_AssertPass("Call to SDL_setenv('','%s', %i)", value1, overwrite);
+    SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result);
+    result = SDL_setenv("=", value1, overwrite);
+    SDLTest_AssertPass("Call to SDL_setenv('=','%s', %i)", value1, overwrite);
+    SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result);
+    result = SDL_setenv(name, NULL, overwrite);
+    SDLTest_AssertPass("Call to SDL_setenv('%s', NULL, %i)", name, overwrite);
+    SDLTest_AssertCheck(result == -1, "Check result, expected: -1, got: %i", result);
+  }
+
+  /* Clean up */
+  SDL_free(value1);
+  SDL_free(value2);
+    
+  return TEST_COMPLETED;
+}
+
 /* ================= Test References ================== */
 
 /* Standard C routine test cases */
@@ -128,14 +262,17 @@
 static const SDLTest_TestCaseReference stdlibTest2 =
         { (SDLTest_TestCaseFp)stdlib_snprintf, "stdlib_snprintf", "Call to SDL_snprintf", TEST_ENABLED };
 
+static const SDLTest_TestCaseReference stdlibTest3 =
+        { (SDLTest_TestCaseFp)stdlib_getsetenv, "stdlib_getsetenv", "Call to SDL_getenv and SDL_setenv", TEST_ENABLED };
+
 /* Sequence of Standard C routine test cases */
 static const SDLTest_TestCaseReference *stdlibTests[] =  {
-    &stdlibTest1, &stdlibTest2, NULL
+    &stdlibTest1, &stdlibTest2, &stdlibTest3, NULL
 };
 
 /* Timer test suite (global) */
 SDLTest_TestSuiteReference stdlibTestSuite = {
-    "Standard C routines",
+    "Stdlib",
     NULL,
     stdlibTests,
     NULL
--- a/test/testautomation_suites.h	Wed Mar 19 22:43:30 2014 -0400
+++ b/test/testautomation_suites.h	Wed Mar 19 21:39:55 2014 -0700
@@ -26,6 +26,7 @@
 extern SDLTest_TestSuiteReference syswmTestSuite;
 extern SDLTest_TestSuiteReference timerTestSuite;
 extern SDLTest_TestSuiteReference videoTestSuite;
+extern SDLTest_TestSuiteReference hintsTestSuite;
 
 /* All test suites */
 SDLTest_TestSuiteReference *testSuites[] =  {
@@ -46,6 +47,7 @@
     &syswmTestSuite,
     &timerTestSuite,
     &videoTestSuite,
+    &hintsTestSuite,
     NULL
 };