FS-12048: [Core] Fix leak in SQLite (switch_cache_db_execute_sql2str) when queries return a NULL containing field which may result in high memory consumption.

This commit is contained in:
Andrey Volk 2019-09-13 20:28:38 +04:00
parent fc61fcfe60
commit 4eca43bc62
7 changed files with 319 additions and 35 deletions

View File

@ -586,6 +586,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_pgsql", "src\mod\databa
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_mariadb", "src\mod\databases\mod_mariadb\mod_mariadb.2017.vcxproj", "{0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_switch_core_db", "tests\unit\test_switch_core_db.2017.vcxproj", "{580675D7-C1C9-4197-AAC5-00F64FAFDE78}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
All|Win32 = All|Win32
@ -2689,6 +2691,18 @@ Global
{0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.Release|Win32.Build.0 = Release|Win32
{0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.Release|x64.ActiveCfg = Release|x64
{0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC}.Release|x64.Build.0 = Release|x64
{580675D7-C1C9-4197-AAC5-00F64FAFDE78}.All|Win32.ActiveCfg = Release|Win32
{580675D7-C1C9-4197-AAC5-00F64FAFDE78}.All|Win32.Build.0 = Release|Win32
{580675D7-C1C9-4197-AAC5-00F64FAFDE78}.All|x64.ActiveCfg = Release|x64
{580675D7-C1C9-4197-AAC5-00F64FAFDE78}.All|x64.Build.0 = Release|x64
{580675D7-C1C9-4197-AAC5-00F64FAFDE78}.Debug|Win32.ActiveCfg = Debug|Win32
{580675D7-C1C9-4197-AAC5-00F64FAFDE78}.Debug|Win32.Build.0 = Debug|Win32
{580675D7-C1C9-4197-AAC5-00F64FAFDE78}.Debug|x64.ActiveCfg = Debug|x64
{580675D7-C1C9-4197-AAC5-00F64FAFDE78}.Debug|x64.Build.0 = Debug|x64
{580675D7-C1C9-4197-AAC5-00F64FAFDE78}.Release|Win32.ActiveCfg = Release|Win32
{580675D7-C1C9-4197-AAC5-00F64FAFDE78}.Release|Win32.Build.0 = Release|Win32
{580675D7-C1C9-4197-AAC5-00F64FAFDE78}.Release|x64.ActiveCfg = Release|x64
{580675D7-C1C9-4197-AAC5-00F64FAFDE78}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -2901,6 +2915,7 @@ Global
{BC1FD72E-1CD5-4525-A7F5-17C5740BFDED} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B}
{1BA65811-5453-46F6-8190-9ECEEFEB7DF2} = {31C2761D-20E0-4BF8-98B9-E32F0D8DD6E1}
{0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC} = {31C2761D-20E0-4BF8-98B9-E32F0D8DD6E1}
{580675D7-C1C9-4197-AAC5-00F64FAFDE78} = {9388C266-C3FC-468A-92EF-0CBC35941412}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {09840DE7-9208-45AA-9667-1A71EE93BD1E}

View File

@ -103,41 +103,42 @@ SWITCH_DECLARE(int) switch_core_db_close(switch_core_db_t *db);
SWITCH_DECLARE(int) switch_core_db_open(const char *filename, switch_core_db_t **ppDb);
/**
* The next group of routines returns information about the information
* in a single column of the current result row of a query. In every
* case the first parameter is a pointer to the SQL statement that is being
* executed (the switch_core_db_stmt_t* that was returned from switch_core_db_prepare()) and
* the second argument is the index of the column for which information
* should be returned. iCol is zero-indexed. The left-most column as an
* index of 0.
* ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(),
* even empty strings, are always zero-terminated. ^The return
* value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
*
* If the SQL statement is not currently point to a valid row, or if the
* the colulmn index is out of range, the result is undefined.
* ^The object returned by [sqlite3_column_value()] is an
* [unprotected sqlite3_value] object. An unprotected sqlite3_value object
* may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()].
* If the [unprotected sqlite3_value] object returned by
* [sqlite3_column_value()] is used in any other way, including calls
* to routines like [sqlite3_value_int()], [sqlite3_value_text()],
* or [sqlite3_value_bytes()], then the behavior is undefined.
*
* These routines attempt to convert the value where appropriate. For
* These routines attempt to convert the value where appropriate. ^For
* example, if the internal representation is FLOAT and a text result
* is requested, sprintf() is used internally to do the conversion
* automatically. The following table details the conversions that
* are applied:
* is requested, [sqlite3_snprintf()] is used internally to perform the
* conversion automatically. ^(The following table details the conversions
* that are applied:
*
* Internal Type Requested Type Conversion
* ------------- -------------- --------------------------
* NULL INTEGER Result is 0
* NULL FLOAT Result is 0.0
* NULL TEXT Result is an empty string
* NULL BLOB Result is a zero-length BLOB
* NULL TEXT Result is a NULL pointer
* NULL BLOB Result is a NULL pointer
* INTEGER FLOAT Convert from integer to float
* INTEGER TEXT ASCII rendering of the integer
* INTEGER BLOB Same as for INTEGER->TEXT
* FLOAT INTEGER Convert from float to integer
* INTEGER BLOB Same as INTEGER->TEXT
* FLOAT INTEGER [CAST] to INTEGER
* FLOAT TEXT ASCII rendering of the float
* FLOAT BLOB Same as FLOAT->TEXT
* TEXT INTEGER Use atoi()
* TEXT FLOAT Use atof()
* FLOAT BLOB [CAST] to BLOB
* TEXT INTEGER [CAST] to INTEGER
* TEXT FLOAT [CAST] to REAL
* TEXT BLOB No change
* BLOB INTEGER Convert to TEXT then use atoi()
* BLOB FLOAT Convert to TEXT then use atof()
* BLOB TEXT Add a "\000" terminator if needed
* BLOB INTEGER [CAST] to INTEGER
* BLOB FLOAT [CAST] to REAL
* BLOB TEXT Add a zero terminator if needed
*
* Return the value as UTF-8 text.
*/

View File

@ -57,15 +57,7 @@ SWITCH_DECLARE(int) switch_core_db_close(switch_core_db_t *db)
SWITCH_DECLARE(const unsigned char *) switch_core_db_column_text(switch_core_db_stmt_t *stmt, int iCol)
{
const unsigned char *txt = sqlite3_column_text(stmt, iCol);
if (!strcasecmp((char *) stmt, "(null)")) {
memset(stmt, 0, 1);
txt = NULL;
}
return txt;
return sqlite3_column_text(stmt, iCol);
}
SWITCH_DECLARE(const char *) switch_core_db_column_name(switch_core_db_stmt_t *stmt, int N)

View File

@ -884,8 +884,6 @@ SWITCH_DECLARE(char *) switch_cache_db_execute_sql2str(switch_cache_db_handle_t
if ((txt = switch_core_db_column_text(stmt, 0))) {
switch_copy_string(str, (char *) txt, len);
status = SWITCH_STATUS_SUCCESS;
} else {
goto end;
}
}
break;

View File

@ -2,7 +2,7 @@ include $(top_srcdir)/build/modmake.rulesam
noinst_PROGRAMS = switch_event switch_hash switch_ivr_originate switch_utils switch_core switch_console switch_vpx switch_core_file \
switch_ivr_play_say switch_core_codec switch_rtp
noinst_PROGRAMS+= switch_core_video
noinst_PROGRAMS+= switch_core_video switch_core_db
AM_LDFLAGS = -avoid-version -no-undefined $(SWITCH_AM_LDFLAGS) $(openssl_LIBS)
AM_LDFLAGS += $(FREESWITCH_LIBS) $(switch_builddir)/libfreeswitch.la $(CORE_LIBS) $(APR_LIBS)
AM_CFLAGS = $(SWITCH_AM_CPPFLAGS)

View File

@ -0,0 +1,75 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2018, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Chris Rienzo <chris@signalwire.com>
* Andrey Volk <andrey@signalwire.com>
*
*
* switch_core_db.c -- tests core db functions
*
*/
#include <switch.h>
#include <stdlib.h>
#include <test/switch_test.h>
FST_CORE_BEGIN("./conf")
{
FST_SUITE_BEGIN(switch_core_db)
{
FST_SETUP_BEGIN()
{
}
FST_SETUP_END()
FST_TEARDOWN_BEGIN()
{
}
FST_TEARDOWN_END()
FST_TEST_BEGIN(test_switch_cache_db_execute_sql2str)
{
switch_cache_db_handle_t *dbh = NULL;
char *dsn = "test_switch_cache_db_execute_sql2str.db";
char res1[20] = "test";
char res2[20] = "test";
if (switch_cache_db_get_db_handle_dsn(&dbh, dsn) == SWITCH_STATUS_SUCCESS) {
switch_cache_db_execute_sql2str(dbh, "SELECT 1", (char *)&res1, 20, NULL);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "SELECT 1: %s\n", switch_str_nil(res1));
switch_cache_db_execute_sql2str(dbh, "SELECT NULL", (char *)&res2, 20, NULL);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "SELECT NULL: %s\n", switch_str_nil(res2));
}
fst_check_string_equals(res1, "1");
fst_check_string_equals(res2, "");
}
FST_TEST_END()
}
FST_SUITE_END()
}
FST_CORE_END()

View File

@ -0,0 +1,203 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>test_switch_core_db</ProjectName>
<RootNamespace>test_switch_core_db</RootNamespace>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
<ProjectGuid>{580675D7-C1C9-4197-AAC5-00F64FAFDE78}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)w32\winlibs.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)w32\winlibs.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)w32\winlibs.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)w32\winlibs.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(PlatformName)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(PlatformName)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(PlatformName)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(PlatformName)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(PlatformName)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SWITCH_TEST_BASE_DIR_FOR_CONF="..\\..\\tests\\unit\\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<BuildLog />
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnablePREfast>true</EnablePREfast>
<DisableSpecificWarnings>6031;6340;6246;6011;6387;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<BuildLog />
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnablePREfast>true</EnablePREfast>
<DisableSpecificWarnings>6031;6340;6246;6011;6387;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<BuildLog />
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>6031;6340;6246;6011;6387;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<BuildLog />
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>6031;6340;6246;6011;6387;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="switch_core_db.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)w32\Library\FreeSwitchCore.2017.vcxproj">
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>