public static PhpToken[] GetBlock(PhpToken[] tokens, int index) { var start = index; if (tokens[index].TokenType != PhpTokenType.LeftBrace) { throw new InvalidOperationException("Block must begin with a left brace."); } int depth = 1; while (depth != 0) { var t = tokens[++index]; if (t.TokenType == PhpTokenType.LeftBrace) { depth++; } else if (t.TokenType == PhpTokenType.RightBrace) { depth--; } } var tokenCount = index - start + 1; var blockTokens = new PhpToken[tokenCount]; Array.Copy(tokens, start, blockTokens, 0, tokenCount); return blockTokens; }
public string AnnotateBlock(string file, string code, PhpToken[] tokens, int tokenIndex, bool functionsOnly) { if (tokens[tokenIndex - 1].TokenType != PhpTokenType.RightParenthesis && !tokens[tokenIndex - 1].IsKeyword()) { return code; } for (int i = tokenIndex; i >= 0; i--) { if (tokens[i].IsKeyword()) { if (tokens[i].Lexeme == "switch" || (functionsOnly && tokens[i].Lexeme != "function")) return code; break; } } code = Annotate(file, code, tokens[tokenIndex].Index + 1); return code; }
public static PhpToken[] GetGlobalFunctionCallIds(PhpToken[] tokens) { var functionCalls = new List<PhpToken>(); int state = 0; for (int i = 0; i < tokens.Length; i++) { if (state == 0 && (tokens[i].TokenType == PhpTokenType.ObjectOperator || tokens[i].TokenType == PhpTokenType.ScopeResolutionOperator)) state = -1; else if ((state == 0 || state == 1) && tokens[i].TokenType == PhpTokenType.Identifier) state = 1; else if (state == 1 && tokens[i].TokenType == PhpTokenType.LeftParenthesis) { functionCalls.Add(tokens[i - 1]); state = 0; } else if (tokens[i].TokenType != PhpTokenType.WhiteSpace && tokens[i].TokenType != PhpTokenType.Comment) state = 0; } return functionCalls.ToArray(); }
protected string GetSurroundingCode(string code, PhpToken token) { var line = code.GetLineNumber(token.Index); var code2 = code.InsertLineNumbers(); var index = code2.GetLineIndex(line); return code2.GetSurroundingLines(index, 9, 9); }
public override StaticAnalysisAlert[] GetAlerts(string code, PhpToken[] tokens) { return tokens .Where(x => x.TokenType == PhpTokenType.BacktickString && Php.Superglobals .Any(y => x.Lexeme.Contains(y))) .Select(x => CreateAlert(code, x)) .ToArray(); }
public ExpressionWalker(PhpToken[] tokens, params ExpressionAnalyzer[] analyzers) { Analyzers = new List<ExpressionAnalyzer>(); if (analyzers != null) { Analyzers.AddRange(analyzers); } _tokens = tokens; }
public static void IsValid(TokenPairs pairs) { var text = string.Join("", pairs.Select(pair => pair.Value).ToArray()); var lexer = new PhpLexer(text); int index = 0; var expected = pairs.Select(pair => { var token = new PhpToken(pair.Key, pair.Value, index); index += pair.Value.Length; return token; }); List<PhpToken> actual = lexer.GetTokens(); CollectionAssert.AreEqual(expected, actual); }
public static Dictionary<string, List<string>> FindSuperglobalFields(PhpToken[] tokens) { var fields = PhpParser.GetSuperglobalFields(tokens); foreach (var superglobal in tokens .Where(x => x.TokenType == PhpTokenType.String || x.TokenType == PhpTokenType.HereDocString || x.TokenType == PhpTokenType.BacktickString) .Select(x => GetSuperGlobalFieldsFromText(x.Lexeme)) .SelectMany(x => x)) fields[superglobal.Key].AddRange(superglobal.Value); return fields; }
public void AddValues(string filename, PhpToken[] tokens) { var walker = new ExpressionWalker( tokens, new BooleanExpressionAnalyzer(), new SwitchStatementAnalyzer()); var valueTable = new SuperGlobalValueTable(filename); walker.Walk(); walker.Analyzers.Iter(x => { x.Matches.Iter(y => { var id = y.Tokens[0].Lexeme; var list = valueTable[id]; if (list == null) { list = new SuperGlobalValueList(id); valueTable.Add(list); } Func<string, string> s = a => a.Substring(1, a.Length - 2); if (x is BooleanExpressionAnalyzer) { list.Values.Add( new SuperGlobalNameValuePair( s(y.Tokens[1].Lexeme), s(y.Tokens[3].Lexeme))); } else if (x is SwitchStatementAnalyzer) { list.Values.AddRange( y.Tokens .Skip(2) .Select(z => new SuperGlobalNameValuePair( s(y.Tokens[1].Lexeme), s(z.Lexeme)))); } }); }); lock (PageTable) { PageTable.Add(valueTable); } }
protected override void AnalyzeCore(PhpToken token) { if (token.TokenType == PhpTokenType.WhiteSpace || token.TokenType == PhpTokenType.Comment) { return; } else if (State == 0 && token.TokenType == PhpTokenType.Variable && PhpName.Superglobals.Contains(token.Lexeme)) { AddExpressionToken(); } else if (State == 1 && token.TokenType == PhpTokenType.LeftBracket) { State++; } else if (State == 2 && token.TokenType == PhpTokenType.String) { AddExpressionToken(); } else if (State == 3 && token.TokenType == PhpTokenType.RightBracket) { State++; } else if (State == 4 && _operators.Contains(token.TokenType)) { AddExpressionToken(); } else if (State == 5 && token.TokenType == PhpTokenType.String) { AddExpressionToken(); AddExpression(); } else { NewExpression(); } }
public static PhpToken[] GetArrayAccesses(PhpToken[] tokens) { var functionCalls = new List<PhpToken>(); int state = 0; for (int i = 0; i < tokens.Length; i++) { if ((state == 0 || state == 1) && tokens[i].TokenType == PhpTokenType.Variable) state = 1; else if (state == 1 && tokens[i].TokenType == PhpTokenType.LeftBracket) { functionCalls.Add(tokens[i - 1]); state = 0; } else if (tokens[i].TokenType != PhpTokenType.WhiteSpace && tokens[i].TokenType != PhpTokenType.Comment) state = 0; } return functionCalls.ToArray(); }
public override StaticAnalysisAlert[] GetAlerts(string code, PhpToken[] tokens) { var functions = PhpParser.GetGlobalFunctionCalls(tokens); var sanitizationFunctions = GetSanitizationFunctions(); var targetFunctionNames = GetFunctions(); var targetFunctionCalls = functions .Where(x => targetFunctionNames.Contains(x.Id.Lexeme) && !x.ParamTokens.Any(y => sanitizationFunctions.Contains(y.Lexeme))); var insecureCalls = targetFunctionCalls.Where(IsCallInsecure); return insecureCalls .Select(x => { var line = code.GetLineNumber(x.Id.Index); var code2 = code.InsertLineNumbers(); var index = code2.GetLineIndex(line); return new StaticAnalysisAlert(Name, line + 1, code2.GetSurroundingLines(index, 9, 9)); }) .ToArray(); }
public static Dictionary<string, List<string>> GetSuperglobalFields(PhpToken[] tokens) { var fieldDictionary = Php.Superglobals .ToDictionary(x => x, x => new List<string>()); for (int i = 0; i < tokens.Length; i++) if (Php.Superglobals.Contains(tokens[i].Lexeme)) { int state = 0; string fieldName = null; for (int j = i + 1; j < tokens.Length; j++) { if (state == 0 && tokens[j].TokenType == PhpTokenType.LeftBracket) { state = 1; } else if (state == 1 && tokens[j].TokenType == PhpTokenType.String) { state = 2; fieldName = tokens[j].Lexeme; } else if (state == 2 && tokens[j].TokenType == PhpTokenType.RightBracket) { state = 3; break; } else break; } if (state == 3) { var name = fieldName.Substring(1, fieldName.Length - 2); if (!fieldDictionary[tokens[i].Lexeme].Contains(name)) fieldDictionary[tokens[i].Lexeme].Add(name); } } return fieldDictionary; }
public static string[] GetIncludedFiles(PhpToken[] tokens) { var includedFiles = new List<string>(); for (int i = 0; i < tokens.Length; i++) if (Php.IncludeFunctions.Contains(tokens[i].Lexeme)) { int state = 0; string filename = null; for (int j = i + 1; j < tokens.Length; j++) { if (state == 0 && tokens[j].TokenType == PhpTokenType.LeftParenthesis) { state = 1; } else if (state == 0 && tokens[j].TokenType == PhpTokenType.String) { state = 4; filename = tokens[j].Lexeme; } else if (state == 1 && tokens[j].TokenType == PhpTokenType.String) { state = 2; filename = tokens[j].Lexeme; } else if (state == 2 && tokens[j].TokenType == PhpTokenType.RightParenthesis) { state = 3; break; } else if (state == 4 && tokens[j].TokenType == PhpTokenType.EndOfStatement) { state = 3; break; } else break; } if (state == 3) { includedFiles.Add(filename.Substring(1, filename.Length - 2)); } } return includedFiles.ToArray(); }
public void Set(ref string PHP) { var lexer = new PhpLexer(PHP); var tokens = lexer.GetTokens().ToArray(); var unk = tokens.Where(x => x.TokenType == PhpTokenType.Unknown); #if DEBUG if (unk.Any()) throw new InvalidOperationException(); #endif var funcTokens = StartDelimiter == '(' ? PhpParser.GetGlobalFunctionCallIds(tokens) : PhpParser.GetArrayAccesses(tokens); for (int i = funcTokens.Length - 1; i >= 0; i--) { if (funcTokens[i].Lexeme != FunctionName) continue; if (StartDelimiter == '(') { PHP = PHP.Remove(funcTokens[i].Index, funcTokens[i].Lexeme.Length); PHP = PHP.Insert(funcTokens[i].Index, ReplacementName); } else { var tokenIndex = Array.IndexOf(tokens, tokens.Single(x => x.Index == funcTokens[i].Index)); PhpToken leftBracket = new PhpToken(), rightBracket = new PhpToken(); for (int j = tokenIndex + 1; j < tokens.Length; j++) { if (tokens[j].TokenType == PhpTokenType.LeftBracket) leftBracket = tokens[j]; else if (tokens[j].TokenType == PhpTokenType.RightBracket) { rightBracket = tokens[j]; break; } } if (leftBracket.TokenType != PhpTokenType.LeftBracket) continue; PHP = PHP.Insert(rightBracket.Index, ")"); PHP = PHP.Insert(leftBracket.Index + 1, ReplacementName + "("); } } }
protected StaticAnalysisAlert CreateAlert(string code, PhpToken token) { return new StaticAnalysisAlert(Name, code.GetLineNumber(token.Index) + 1, GetSurroundingCode(code, token)); }
public abstract StaticAnalysisAlert[] GetAlerts(string code, PhpToken[] tokens);
protected override void AnalyzeCore(PhpToken token) { if (token.TokenType == PhpTokenType.WhiteSpace || token.TokenType == PhpTokenType.Comment) { return; } else if (State == 0 && token.TokenType == PhpTokenType.switchKeyword) { State++; } else if (State == 1 && token.TokenType == PhpTokenType.LeftParenthesis) { State++; } else if (State == 2 && token.TokenType == PhpTokenType.Variable && Php.Superglobals.Contains(token.Lexeme)) { AddExpressionToken(); } else if (State == 3 && token.TokenType == PhpTokenType.LeftBracket) { State++; } else if (State == 4 && token.TokenType == PhpTokenType.String) { AddExpressionToken(); } else if (State == 5 && token.TokenType == PhpTokenType.RightBracket) { State++; } else if (State == 6 && token.TokenType == PhpTokenType.RightParenthesis) { State++; } else if (State == 7) { if (token.TokenType == PhpTokenType.RightBrace) { AddExpression(); } else if (token.TokenType == PhpTokenType.caseKeyword) { State++; } } else if (State == 8) { if (token.TokenType == PhpTokenType.String) { AddExpressionToken(); } State = 7; } else { NewExpression(); } }
public static PhpToken[] StripWhitespaceAndComments(PhpToken[] tokens) { return tokens .Where(x => x.TokenType != PhpTokenType.WhiteSpace && x.TokenType != PhpTokenType.Comment) .ToArray(); }
protected abstract void AnalyzeCore(PhpToken token);
public void Analyze(PhpToken token) { _currentToken = token; AnalyzeCore(token); }
public IEnumerable<StaticAnalysisAlert> GetAlerts(string code, PhpToken[] tokens) { return _plugins.SelectMany(x => x.GetAlerts(code, tokens)); }
public string AnnotateCode(string file, string php, PhpToken[] tokens) { lock (AnnotationIndexes) { AnnotationIndexes.Add(file, 0); AnnotationTable.Add(file); } for (int i = tokens.Length - 1; i >= 0; i--) { if (tokens[i].TokenType == PhpTokenType.LeftBrace) { php = AnnotateBlock(file, php, tokens, i, Config.CodeCoverageReport == 1); } } var open = tokens.FirstOrDefault(x => x.TokenType == PhpTokenType.OpenTag); if (open.Lexeme != null) { php = Annotate(file, php, open.Index + open.Lexeme.Length); } else { var tmp = Annotate(file, "<?php ?>", 6); php = tmp + php; } return php; }
public FunctionCall(PhpToken id, PhpToken[] parameters) { Id = id; ParamTokens = parameters; }
public static List<FunctionCall> GetGlobalFunctionCalls(PhpToken[] tokens) { int state = 0; var calls = new List<FunctionCall>(); FunctionCall call = new FunctionCall(); List<PhpToken> paramTokens = null; for (int i = 0; i < tokens.Length; i++) { if (state == 0 && (tokens[i].TokenType == PhpTokenType.ObjectOperator || tokens[i].TokenType == PhpTokenType.ScopeResolutionOperator)) state = -1; else if ((state == 0 || state == 1) && (tokens[i].TokenType == PhpTokenType.Identifier || tokens[i].TokenType == PhpTokenType.Variable)) { state = 1; call = new FunctionCall(); call.Id = tokens[i]; paramTokens = new List<PhpToken>(); } else if (state == 1 && tokens[i].TokenType == PhpTokenType.LeftParenthesis) { paramTokens.Add(tokens[i]); state = 2; } else if (state > 1) { paramTokens.Add(tokens[i]); if (tokens[i].TokenType == PhpTokenType.LeftParenthesis) state++; else if (tokens[i].TokenType == PhpTokenType.RightParenthesis) state--; if (state <= 1) { call.ParamTokens = paramTokens.ToArray(); calls.Add(call); state = 0; } } else if (tokens[i].TokenType != PhpTokenType.WhiteSpace && tokens[i].TokenType != PhpTokenType.Comment) state = 0; } return calls; }
public void Token_ToString() { var token = new PhpToken(PhpTokenType.OpenTag, "<?", 0); Assert.AreEqual("[0] OpenTag: <?", token.ToString()); }