노현종

C언어 GetCriticalBlocks 크리티컬 블록 완성

코드 block별로 크리티컬과 넌크리티컬 완벽히 나눠짐
......@@ -10,9 +10,18 @@ using System.Threading.Tasks;
namespace VulnCrawler
{
// 추상 클래스
public abstract class VulnAbstractCrawler
{
public class Block
{
public int Num { get; set; }
public bool HasCritical { get; set; }
public string Code { get; set; }
public string Hash { get; set; }
}
protected Regex extractMethodLine;
protected HashSet<string> ReservedList { get; }
protected abstract string ReservedFileName { get; }
......@@ -106,7 +115,7 @@ namespace VulnCrawler
/// <returns>함수 문자열</returns>
protected abstract string GetOriginalFunc(Stream oldStream, string methodName);
protected abstract IList<string> GetCriticalBlocks(string srcCode, IEnumerable<string> criticalList);
protected abstract IList<Block> GetCriticalBlocks(string srcCode, IEnumerable<string> criticalList);
/// <summary>
/// 성능 개선을 위한
/// 코드 라인 위치 기반 취약 원본 함수 추출 테스트용 함수 곧 삭제 예정
......@@ -226,13 +235,14 @@ namespace VulnCrawler
public abstract IDictionary<string, IEnumerable<string>> ExtractGitCriticalMethodTable(string srcCode);
/// <summary>
/// 실제 프로세스
/// 패치 전 코드 파일과 크리티컬 메서드 테이블로 부터 크리티컬 블록 추출
/// </summary>
/// <param name="oldStream"></param>
/// <param name="methodName"></param>
/// <param name="oldBlob">패치 전 파일 Blob</param>
/// <param name="table">크리티컬 메서드 테이블(Key: 메서드 이름, Value: 변수 리스트)</param>
/// <returns></returns>
public virtual IEnumerable<(string originalFunc, string hash)> Process(Blob oldBlob, IDictionary<string, IEnumerable<string>> table) {
public virtual IEnumerable<(string methodName, IList<Block> blocks)> Process(Blob oldBlob, IDictionary<string, IEnumerable<string>> table) {
foreach (var item in table)
{
string methodName = item.Key;
......@@ -243,21 +253,23 @@ namespace VulnCrawler
Console.WriteLine(func);
string bs = string.Empty;
string md5 = string.Empty;
int blockNum = 1;
if (item.Value.Count() != 0)
{
var blocks = GetCriticalBlocks(func, item.Value);
StringBuilder builder = new StringBuilder();
// 크리티컬 블록 추출
var blocks = GetCriticalBlocks(func, item.Value).ToList();
if (blocks == null)
{
continue;
}
foreach (var block in blocks)
{
Console.WriteLine($"=====block({blockNum})");
Console.WriteLine(block);
builder.AppendLine(block);
block.Hash = MD5HashFunc(block.Code);
}
bs = builder.ToString();
md5 = MD5HashFunc(bs);
yield return (methodName, blocks);
}
yield return (bs, md5);
}
}
/// <summary>
......@@ -274,7 +286,6 @@ namespace VulnCrawler
/// <returns>커밋 목록</returns>
public virtual IEnumerable<Commit> SearchCommits() {
// where => 조건에 맞는 것을 찾음(CVE-20\d\d-\d{4}로 시작하는 커밋만 골라냄)
Console.WriteLine("출력중");
Console.WriteLine(Repository.Commits.Count());
var commits = Repository.Commits
.Where(c => Regex.Match(c.Message, SearchCommitPattern, RegexOptions.IgnoreCase).Success)
......
......@@ -227,11 +227,11 @@ namespace VulnCrawler
return oldBuilder.ToString();
}
protected override IList<string> GetCriticalBlocks(string srcCode, IEnumerable<string> criticalList)
protected override IList<Block> GetCriticalBlocks(string srcCode, IEnumerable<string> criticalList)
{
var split = srcCode.Split('\n');
int bracketCount = 0;
var blockList = new List<string>();
var blockList = new List<Block>();
StringBuilder builder = new StringBuilder();
var crList = criticalList as HashSet<string>;
if (crList == null)
......@@ -239,6 +239,8 @@ namespace VulnCrawler
return null;
}
bool mainLine = true; /* 현재 라인이 메인 코드 라인인지 */
bool criticalBlock = false; /* 현재 라인이 메인 코드 라인인지 */
int blockNum = 1; /* 현재 라인이 메인 코드 라인인지 */
foreach (var line in split)
{
string trim = line.Trim();
......@@ -248,6 +250,11 @@ namespace VulnCrawler
int subtract = openBracketCount - closeBracketCount;
bracketCount += subtract;
if (trim.Equals("}"))
{
builder.AppendLine(line);
continue;
}
/* 중괄호 연산 결과 1이라는 것은 메인 라인 */
if (bracketCount == 1)
{
......@@ -261,7 +268,9 @@ namespace VulnCrawler
string s = builder.ToString();
if (!string.IsNullOrWhiteSpace(s))
{
blockList.Add(s);
blockList.Add(new Block() { HasCritical = criticalBlock, Code = s, Num = blockNum });
blockNum++;
criticalBlock = false;
builder.Clear();
}
}
......@@ -280,7 +289,9 @@ namespace VulnCrawler
string s = builder.ToString();
if (!string.IsNullOrWhiteSpace(s))
{
blockList.Add(s);
blockList.Add(new Block() { HasCritical = criticalBlock, Code = s, Num = blockNum });
blockNum++;
criticalBlock = false;
builder.Clear();
}
}
......@@ -291,19 +302,31 @@ namespace VulnCrawler
{
continue;
}
/* 현재 코드 라인에서 변수 추출시켜서 크리티컬 리스트와 대조 */
foreach (var var in ExtractCriticalVariant(line))
{
/* 크리티컬 리스트에 추출한 변수가 들어있다면 추가 */
if (criticalList.Contains(var))
{
builder.AppendLine(line);
criticalBlock = true;
break;
}
}
builder.AppendLine(line);
}
/* 마지막 남은게 있을 수 있으니 추가 */
string fs = builder.ToString();
if (!string.IsNullOrWhiteSpace(fs))
{
blockList.Add(new Block() { HasCritical = criticalBlock, Code = fs, Num = blockNum });
blockNum++;
criticalBlock = false;
builder.Clear();
}
return blockList;
}
}
......
......@@ -71,7 +71,7 @@ namespace VulnCrawler
throw new NotImplementedException();
}
protected override IList<string> GetCriticalBlocks(string srcCode, IEnumerable<string> criticalList)
protected override IList<Block> GetCriticalBlocks(string srcCode, IEnumerable<string> criticalList)
{
throw new NotImplementedException();
}
......
......@@ -89,15 +89,26 @@ namespace VulnCrawler
Console.ResetColor();
var table = self.ExtractGitCriticalMethodTable(entry.Patch);
string originalFunc = string.Empty, md5 = string.Empty;
foreach (var tuple in self.Process(oldBlob, table))
{
Console.WriteLine("===z");
(originalFunc, md5) = tuple;
// 패치 전 원본 함수
Console.WriteLine($"Original Func: {originalFunc}");
// 해쉬 후
Console.WriteLine($"Original Func MD5: {md5}");
(var methodName, var blocks) = tuple;
foreach (var block in blocks)
{
if (block.HasCritical)
{
Console.BackgroundColor = ConsoleColor.DarkMagenta;
}
else
{
Console.BackgroundColor = ConsoleColor.DarkGreen;
}
Console.WriteLine($"=====block({block.Num}, {block.HasCritical.ToString()})");
Console.WriteLine(block.Code);
Console.ResetColor();
Console.WriteLine($"MD5 = {block.Hash}");
}
}
......