Skip to content

Commit

Permalink
Merge pull request #44 from chequer-io/feature/QD-597
Browse files Browse the repository at this point in the history
[QD-597] Impl MySql Statements & QsiSensitiveData
  • Loading branch information
Kimhwiwoong committed Mar 15, 2023
2 parents 5622aa6 + a35e56a commit e99853b
Show file tree
Hide file tree
Showing 39 changed files with 930 additions and 15 deletions.
27 changes: 25 additions & 2 deletions Qsi.Debugger/Vendor/MySql/MySqlRepositoryProvider.cs
Expand Up @@ -50,20 +50,43 @@ protected override QsiTableStructure LookupTable(QsiQualifiedIdentifier identifi
csMemoView.Type = QsiTableType.View;
AddColumns(csMemoView, "a", "b");
return csMemoView;

case "hidden_test":
var hiddenTest = CreateTable("sakila", "hidden_test");
AddColumns(hiddenTest, "col1", "hidden1", "col2", "hidden2");
hiddenTest.Columns[1].IsVisible = false;
hiddenTest.Columns[3].IsVisible = false;
return hiddenTest;

case "hidden_test2":
var hiddenTest2 = CreateTable("sakila", "hidden_test2");
AddColumns(hiddenTest2, "col1", "col2", "hidden1", "hidden2");
hiddenTest2.Columns[2].IsVisible = false;
hiddenTest2.Columns[3].IsVisible = false;
return hiddenTest2;

case "user":
var user = CreateTable("mysql", "user");

AddColumns(user, "Host", "User",
"Select_priv", "Insert_priv", "Update_priv", "Delete_priv",
"Create_priv", "Drop_priv", "Reload_priv", "Shutdown_priv",
"Process_priv", "File_priv", "Grant_priv", "References_priv",
"Index_priv", "Alter_priv", "Show_db_priv", "Super_priv",
"Create_tmp_table_priv", "Lock_tables_priv", "Execute_priv",
"Repl_slave_priv", "Repl_client_priv", "Create_view_priv",
"Show_view_priv", "Create_routine_priv", "Alter_routine_priv",
"Create_user_priv", "Event_priv", "Trigger_priv",
"Create_tablespace_priv", "ssl_type", "ssl_cipher",
"x509_issuer", "x509_subject", "max_questions", "max_updates",
"max_connections", "max_user_connections", "plugin",
"authentication_string", "password_expired",
"password_last_changed", "password_lifetime",
"account_locked", "Create_role_priv", "Drop_role_priv",
"Password_reuse_history", "Password_reuse_time",
"Password_require_current", "User_attributes", "password");

return user;
}

return null;
Expand Down
91 changes: 91 additions & 0 deletions Qsi.MySql/Analyzers/MySqlActionAnalyzer.cs
@@ -0,0 +1,91 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Qsi.Analyzers;
using Qsi.Analyzers.Action;
using Qsi.Analyzers.Context;
using Qsi.Data;
using Qsi.Engines;
using Qsi.Extensions;
using Qsi.MySql.Tree;
using Qsi.Tree;

namespace Qsi.MySql.Analyzers;

public class MySqlActionAnalyzer : QsiActionAnalyzer
{
public MySqlActionAnalyzer(QsiEngine engine) : base(engine)
{
}

protected override async ValueTask<IQsiAnalysisResult[]> ExecuteDataUpdateAction(IAnalyzerContext context, IQsiDataUpdateActionNode action)
{
IQsiAnalysisResult[] result = await base.ExecuteDataUpdateAction(context, action);

if (result.FirstOrDefault() is { } firstResult &&
action.Target is IQsiDerivedTableNode { Where: { } whereExpr })
{
IEnumerable<IQsiExpressionNode> nodes = action.SetValues
.Select(values => values.Value)
.Append(whereExpr.Expression);

AddSensitiveData(firstResult.SensitiveDataCollection, nodes);
}

return result;
}

protected override async ValueTask<IQsiAnalysisResult[]> ExecuteDataDeleteAction(IAnalyzerContext context, IQsiDataDeleteActionNode action)
{
IQsiAnalysisResult[] result = await base.ExecuteDataDeleteAction(context, action);

if (result.FirstOrDefault() is { } firstResult &&
action.Target is IQsiDerivedTableNode { Where: { } whereExpr })
{
AddSensitiveData(firstResult.SensitiveDataCollection, whereExpr.Expression);
}

return result;
}

protected override QsiVariableSetActionResult ResolveVariableSet(IAnalyzerContext context, IQsiVariableSetItemNode node)
{
var result = base.ResolveVariableSet(context, node);

if (result.Name.Value is "PASSWORD")
result.SensitiveDataCollection.Add(CreateSensitiveData(QsiSensitiveDataType.Password, node.Expression));

return result;
}

protected override QsiUserInfo ResolveUser(IAnalyzerContext context, IQsiUserNode node, QsiSensitiveDataCollection dataCollection)
{
var result = base.ResolveUser(context, node, dataCollection);

if (node.Password is { })
dataCollection.Add(CreateSensitiveData(QsiSensitiveDataType.Password, node.Password));

return result;
}

private void AddSensitiveData(QsiSensitiveDataCollection collection, IEnumerable<IQsiExpressionNode> nodes)
{
AddSensitiveData(collection, nodes.ToArray());
}

private void AddSensitiveData(QsiSensitiveDataCollection collection, params IQsiExpressionNode[] nodes)
{
IEnumerable<QsiSensitiveData> sensitiveDatas = nodes
.SelectMany(n => n.Flatten())
.Select(e => (e, MySqlTree.SensitiveType[e]))
.Where(e => e.Item2 is not QsiSensitiveDataType.None)
.Select(e => CreateSensitiveData(e.Item2, e.e));

collection.AddRange(sensitiveDatas);
}

protected override QsiSensitiveData CreateSensitiveData(QsiSensitiveDataType dataType, IQsiTreeNode node)
{
return new QsiSensitiveData(dataType, MySqlTree.Span[node]);
}
}
2 changes: 1 addition & 1 deletion Qsi.MySql/MySqlLanguageServiceBase.cs
Expand Up @@ -46,7 +46,7 @@ public override QsiAnalyzerOptions CreateAnalyzerOptions()

public override IEnumerable<QsiAnalyzerBase> CreateAnalyzers(QsiEngine engine)
{
yield return new QsiActionAnalyzer(engine);
yield return new MySqlActionAnalyzer(engine);
yield return new MySqlTableAnalyzer(engine);
yield return new QsiDefinitionAnalyzer(engine);
}
Expand Down
24 changes: 24 additions & 0 deletions Qsi.MySql/MySqlParser.cs
Expand Up @@ -50,6 +50,12 @@ public IQsiTreeNode Parse(QsiScript script, CancellationToken cancellationToken
case UtilityStatementContext utilityStatement:
return ParseUtilityStatement(utilityStatement);

case AccountManagementStatementContext accountManagementStatement:
return ParseAccountManagementStatement(accountManagementStatement);

case SetStatementContext setStatement:
return ActionVisitor.VisitSetStatement(setStatement);

default:
throw TreeHelper.NotSupportedTree(simpleStatement.children[0]);
}
Expand All @@ -66,5 +72,23 @@ private IQsiTreeNode ParseUtilityStatement(UtilityStatementContext context)
throw TreeHelper.NotSupportedTree(context.children[0]);
}
}

private IQsiTreeNode ParseAccountManagementStatement(AccountManagementStatementContext context)
{
switch (context.children[0])
{
case CreateUserContext createUser:
return ActionVisitor.VisitCreateUser(createUser);

case AlterUserContext alterUser:
return ActionVisitor.VisitAlterUser(alterUser);

case GrantContext grant:
return ActionVisitor.VisitGrant(grant);

default:
throw TreeHelper.NotSupportedTree(context.children[0]);
}
}
}
}
28 changes: 28 additions & 0 deletions Qsi.MySql/Tree/MySqlTree.cs
@@ -1,6 +1,7 @@
using System;
using System.Runtime.CompilerServices;
using Antlr4.Runtime;
using Qsi.Data;
using Qsi.Shared;
using Qsi.Tree;
using Qsi.Tree.Data;
Expand All @@ -13,10 +14,13 @@ internal static class MySqlTree

public static KeyIndexer<bool> IsSimpleParExpr { get; }

public static KeyIndexer<QsiSensitiveDataType> SensitiveType { get; }

static MySqlTree()
{
Span = new KeyIndexer<Range>(QsiNodeProperties.Span);
IsSimpleParExpr = new KeyIndexer<bool>(new Key<bool>("node::simple_par_expr"));
SensitiveType = new KeyIndexer<QsiSensitiveDataType>(new Key<QsiSensitiveDataType>("node::sensitive_type"));
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down Expand Up @@ -45,5 +49,29 @@ internal static void PutContextSpan(IQsiTreeNode node, IToken start, IToken stop

Span[node] = new Range(startIndex, stopIndex);
}

public static TNode WithContextSpan<TNode>(this TNode node, IParserRuleContext context) where TNode : IQsiTreeNode
{
PutContextSpan(node, context);
return node;
}

public static TNode WithContextSpan<TNode>(this TNode node, ParserRuleContext context) where TNode : IQsiTreeNode
{
PutContextSpan(node, context);
return node;
}

public static TNode WithContextSpan<TNode>(this TNode node, IToken token) where TNode : IQsiTreeNode
{
PutContextSpan(node, token);
return node;
}

public static TNode WithContextSpan<TNode>(this TNode node, IToken start, IToken stop) where TNode : IQsiTreeNode
{
PutContextSpan(node, start, stop);
return node;
}
}
}

0 comments on commit e99853b

Please sign in to comment.