Browse Source

Scrub HTTP and Database parts for invalid char

Sanitizes data library aliases when caching and loading while keeping a
lookup table back to the original values.  Prevents saving invalid data
into the schematic

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20653
master
Seth Hillbrand 1 month ago
parent
commit
65db4a890e
  1. 11
      common/http_lib/http_lib_connection.cpp
  2. 35
      eeschema/sch_io/database/sch_io_database.cpp
  3. 1
      eeschema/sch_io/database/sch_io_database.h

11
common/http_lib/http_lib_connection.cpp

@ -31,6 +31,7 @@
#include <curl/curl.h> #include <curl/curl.h>
#include <http_lib/http_lib_connection.h> #include <http_lib/http_lib_connection.h>
#include <lib_id.h>
const char* const traceHTTPLib = "KICAD_HTTP_LIB"; const char* const traceHTTPLib = "KICAD_HTTP_LIB";
@ -201,6 +202,9 @@ bool HTTP_LIB_CONNECTION::SelectOne( const std::string& aPartID, HTTP_LIB_PART&
else else
aFetchedPart.name = aFetchedPart.id; aFetchedPart.name = aFetchedPart.id;
UTF8 sanitizedFetchedName = LIB_ID::FixIllegalChars( aFetchedPart.name, false );
aFetchedPart.name = sanitizedFetchedName.c_str();
aFetchedPart.symbolIdStr = response.at( "symbolIdStr" ); aFetchedPart.symbolIdStr = response.at( "symbolIdStr" );
// initially assume no exclusion // initially assume no exclusion
@ -335,6 +339,13 @@ bool HTTP_LIB_CONNECTION::SelectAll( const HTTP_LIB_CATEGORY& aCategory, std::ve
else else
part.name = part.id; part.name = part.id;
std::string originalName = part.name;
UTF8 sanitizedPartName = LIB_ID::FixIllegalChars( part.name, false );
part.name = sanitizedPartName.c_str();
if( part.name != originalName )
m_cache.erase( originalName );
// add to cache // add to cache
m_cache[part.name] = std::make_tuple( part.id, aCategory.id ); m_cache[part.name] = std::make_tuple( part.id, aCategory.id );

35
eeschema/sch_io/database/sch_io_database.cpp

@ -20,6 +20,7 @@
#include <iostream> #include <iostream>
#include <unordered_set> #include <unordered_set>
#include <utility>
#include <wx/datetime.h> #include <wx/datetime.h>
#include <wx/log.h> #include <wx/log.h>
@ -29,6 +30,7 @@
#include <database/database_lib_settings.h> #include <database/database_lib_settings.h>
#include <fmt.h> #include <fmt.h>
#include <lib_symbol.h> #include <lib_symbol.h>
#include <lib_id.h>
#include <symbol_lib_table.h> #include <symbol_lib_table.h>
#include "sch_io_database.h" #include "sch_io_database.h"
@ -96,6 +98,8 @@ LIB_SYMBOL* SCH_IO_DATABASE::LoadSymbol( const wxString& aLibraryPath,
if( !m_conn ) if( !m_conn )
THROW_IO_ERROR( m_lastError ); THROW_IO_ERROR( m_lastError );
cacheLib();
/* /*
* Table names are tricky, in order to allow maximum flexibility to the user. * Table names are tricky, in order to allow maximum flexibility to the user.
* The slash character is used as a separator between a table name and symbol name, but symbol * The slash character is used as a separator between a table name and symbol name, but symbol
@ -105,14 +109,26 @@ LIB_SYMBOL* SCH_IO_DATABASE::LoadSymbol( const wxString& aLibraryPath,
* name is blank if our config has an entry for the null table. * name is blank if our config has an entry for the null table.
*/ */
std::string tableName = "";
std::string tableName;
std::string symbolName( aAliasName.ToUTF8() ); std::string symbolName( aAliasName.ToUTF8() );
auto sanitizedIt = m_sanitizedNameMap.find( aAliasName );
if( sanitizedIt != m_sanitizedNameMap.end() )
{
tableName = sanitizedIt->second.first;
symbolName = sanitizedIt->second.second;
}
else
{
tableName.clear();
if( aAliasName.Contains( '/' ) ) if( aAliasName.Contains( '/' ) )
{ {
tableName = std::string( aAliasName.BeforeFirst( '/' ).ToUTF8() ); tableName = std::string( aAliasName.BeforeFirst( '/' ).ToUTF8() );
symbolName = std::string( aAliasName.AfterFirst( '/' ).ToUTF8() ); symbolName = std::string( aAliasName.AfterFirst( '/' ).ToUTF8() );
} }
}
std::vector<const DATABASE_LIB_TABLE*> tablesToTry; std::vector<const DATABASE_LIB_TABLE*> tablesToTry;
@ -209,6 +225,9 @@ void SCH_IO_DATABASE::cacheLib()
return; return;
} }
std::map<wxString, std::unique_ptr<LIB_SYMBOL>> newSymbolCache;
std::map<wxString, std::pair<std::string, std::string>> newSanitizedNameMap;
for( const DATABASE_LIB_TABLE& table : m_settings->m_Tables ) for( const DATABASE_LIB_TABLE& table : m_settings->m_Tables )
{ {
std::vector<DATABASE_CONNECTION::ROW> results; std::vector<DATABASE_CONNECTION::ROW> results;
@ -230,17 +249,25 @@ void SCH_IO_DATABASE::cacheLib()
if( !result.count( table.key_col ) ) if( !result.count( table.key_col ) )
continue; continue;
std::string rawName = std::any_cast<std::string>( result[table.key_col] );
UTF8 sanitizedName = LIB_ID::FixIllegalChars( rawName, false );
std::string sanitizedKey = sanitizedName.c_str();
std::string prefix = table.name.empty() ? "" : fmt::format( "{}/", table.name ); std::string prefix = table.name.empty() ? "" : fmt::format( "{}/", table.name );
wxString name( fmt::format( "{}{}", prefix,
std::any_cast<std::string>( result[table.key_col] ) ) );
std::string sanitizedDisplayName = fmt::format( "{}{}", prefix, sanitizedKey );
wxString name( sanitizedDisplayName );
newSanitizedNameMap[name] = std::make_pair( table.name, rawName );
std::unique_ptr<LIB_SYMBOL> symbol = loadSymbolFromRow( name, table, result ); std::unique_ptr<LIB_SYMBOL> symbol = loadSymbolFromRow( name, table, result );
if( symbol ) if( symbol )
m_nameToSymbolcache[symbol->GetName()] = std::move( symbol );
newSymbolCache[symbol->GetName()] = std::move( symbol );
} }
} }
m_nameToSymbolcache = std::move( newSymbolCache );
m_sanitizedNameMap = std::move( newSanitizedNameMap );
m_cacheTimestamp = currentTimestampSeconds; m_cacheTimestamp = currentTimestampSeconds;
m_cacheModifyHash = m_libTable->GetModifyHash(); m_cacheModifyHash = m_libTable->GetModifyHash();
} }

1
eeschema/sch_io/database/sch_io_database.h

@ -112,6 +112,7 @@ private:
std::set<wxString> m_defaultShownFields; std::set<wxString> m_defaultShownFields;
std::map<wxString, std::unique_ptr<LIB_SYMBOL>> m_nameToSymbolcache; std::map<wxString, std::unique_ptr<LIB_SYMBOL>> m_nameToSymbolcache;
std::map<wxString, std::pair<std::string, std::string>> m_sanitizedNameMap;
long long m_cacheTimestamp; long long m_cacheTimestamp;

Loading…
Cancel
Save