Exemplo n.º 1
0
        public void EmptyTokensVisitorTest()
        {
            string path = (string)TestContext.DataRow["files"];

            if (path.Contains("functions1.phpt"))
            {
                return; // TODO - too slow test
            }
            string testcontent = File.ReadAllText(path);
            var    original    = testcontent;

            if (original.Contains("namespace\\"))
            {
                return; // TODO - current namespace cannot be decided from AST
            }

            var sourceUnit = new TestSourceUnit(original, path, Encoding.UTF8, Lexer.LexicalStates.INITIAL, LanguageFeatures.Php71Set);
            var factory    = new BasicNodesFactory(sourceUnit);
            var errors     = new TestErrorSink();

            sourceUnit.Parse(factory, errors, new TestErrorRecovery());
            GlobalCode ast = sourceUnit.Ast;

            if (errors.Count != 0)
            {
                return; // AST is null or invalid
            }

            var provider = SourceTokenProviderFactory.CreateEmptyProvider();
            var composer = new EmptyComposer(provider);
            var visitor  = new TokenVisitor(new TreeContext(ast), composer, provider);

            visitor.VisitElement(ast);
            var code = composer.Code.ToString();

            var expectedStr = PrepareString(original);
            var actualStr   = PrepareString(code);

            Assert.AreEqual(expectedStr, actualStr);
            var expected = FilterTokens(sourceUnit.SourceLexer.AllTokens);
            var actual   = FilterTokens(composer.Processed);

            Assert.AreEqual(expected.Length, actual.Length);
            for (int i = 0; i < Math.Min(expected.Length, actual.Length); i++)
            {
                if (expected[i].Token == Tokens.T_SEMI && actual[i].Token == Tokens.T_CASE)
                {
                }
                if (expected[i].Token == Tokens.T_LOGICAL_OR && actual[i].Token == Tokens.T_BOOLEAN_OR ||
                    expected[i].Token == Tokens.T_LOGICAL_AND && actual[i].Token == Tokens.T_BOOLEAN_AND)
                {
                }
                else
                {
                    Assert.AreEqual(expected[i].Token, actual[i].Token);
                }
            }


            sourceUnit = new TestSourceUnit(code, path, Encoding.UTF8, Lexer.LexicalStates.INITIAL, LanguageFeatures.Php71Set);
            sourceUnit.Parse(factory, errors, new TestErrorRecovery());
            var newAst = sourceUnit.Ast;

            var serializer        = new JsonNodeWriter();
            var serializerVisitor = new TreeSerializer(serializer);

            ast.VisitMe(visitor);
            expectedStr       = serializer.ToString();
            serializer        = new JsonNodeWriter();
            serializerVisitor = new TreeSerializer(serializer);
            newAst.VisitMe(visitor);
            actualStr = serializer.ToString();
            Assert.AreEqual(expectedStr, actualStr);
        }
Exemplo n.º 2
0
        public TransformationResult Transform(string content, IPolicy policy)
        {
            var result = new TransformationResult();

            var sourceUnit   = new CodeSourceUnit(content, filename, System.Text.Encoding.UTF8, Lexer.LexicalStates.INITIAL, LanguageFeatures.Php71Set);
            var nodesFactory = new BasicNodesFactory(sourceUnit);
            var errors       = new PhpErrorSink();

            sourceUnit.Parse(nodesFactory, errors);
            GlobalCode ast = sourceUnit.Ast;

            if (errors.Count != 0)
            {
                ReportErrors(errors, result, content);
                return(result); // AST is null or invalid
            }

            //collect channel information from source code
            var provider          = SourceTokenProviderFactory.CreateEmptyProvider();
            var collectorComposer = new PhpTokenComposer(provider);
            var collector         = new PhpChannelCollector(policy, new TreeContext(ast), collectorComposer, provider);

            collector.VisitElement(ast);
            result.InputChannels.AddRange(collector.InputChannels);
            result.OutputChannels.AddRange(collector.OutputChannels);
            result.SanitizeChannels.AddRange(collector.SanitizeChannels);

            //if there are no output or input channels found in the code, it makes no sense to transform it
            if (result.OutputChannels.Count == 0 || result.InputChannels.Count == 0)
            {
                return(result);
            }

            var levels = collector.GetDistinctSecurityLevels().OrderByDescending(sl => sl.Level);

            //append a sanitize transformation if there are sanitize channels
            var lowestInputLevel = result.InputChannels.Min(sc => sc.Label.Level);

            if (result.SanitizeChannels.Any())
            {
                var sanSourceUnit   = new CodeSourceUnit(content, filename, System.Text.Encoding.UTF8, Lexer.LexicalStates.INITIAL, LanguageFeatures.Php71Set);
                var sanNodesFactory = new BasicNodesFactory(sourceUnit);
                var sanErrors       = new PhpErrorSink();
                sanSourceUnit.Parse(sanNodesFactory, sanErrors);
                GlobalCode sanAst = sanSourceUnit.Ast;
                if (sanErrors.Count != 0)
                {
                    return(result); // AST is null or invalid
                }

                var pSanitize = new CodeTransformation();
                pSanitize.Kind          = TransformationKind.Sanitize;
                pSanitize.SecurityLevel = new SecurityLevel()
                {
                    Level = lowestInputLevel - 1, Name = "PS"
                };
                var composer = new PhpTokenComposer(provider);
                var rewriter = new PhpChannelRewriter(new TreeContext(sanAst), composer, provider, nodesFactory, policy, collector.InputChannels, collector.OutputChannels, collector.SanitizeChannels, pSanitize.SecurityLevel);
                rewriter.VisitElement(sanAst);
                pSanitize.Code = composer.Code.ToString();

                result.CodeTransformations.Add(pSanitize);
            }

            //create code version for each security level
            foreach (var level in levels)
            {
                var levelSourceUnit   = new CodeSourceUnit(content, filename, System.Text.Encoding.UTF8, Lexer.LexicalStates.INITIAL, LanguageFeatures.Php71Set);
                var levelNodesFactory = new BasicNodesFactory(levelSourceUnit);
                var levelerrors       = new PhpErrorSink();
                levelSourceUnit.Parse(nodesFactory, levelerrors);
                GlobalCode levelAst = levelSourceUnit.Ast;
                if (levelerrors.Count != 0)
                {
                    return(result); // AST is null or invalid
                }


                var version = new CodeTransformation();
                version.Kind          = TransformationKind.Default;
                version.SecurityLevel = level;
                var composer = new PhpTokenComposer(provider);
                var rewriter = new PhpChannelRewriter(new TreeContext(levelAst), composer, provider, levelNodesFactory, policy, collector.InputChannels, collector.OutputChannels, collector.SanitizeChannels, level);
                rewriter.VisitElement(levelAst);
                version.Code = composer.Code.ToString();


                result.CodeTransformations.Add(version);
            }

            //create P version
            var poSourceUnit   = new CodeSourceUnit(content, filename, System.Text.Encoding.UTF8, Lexer.LexicalStates.INITIAL, LanguageFeatures.Php71Set);
            var poNodesFactory = new BasicNodesFactory(poSourceUnit);
            var poErrors       = new PhpErrorSink();

            poSourceUnit.Parse(poNodesFactory, poErrors);
            GlobalCode poAst = poSourceUnit.Ast;

            var po = new CodeTransformation();

            po.Kind = TransformationKind.Original;
            var poComposer = new PhpTokenComposer(provider);

            po.SecurityLevel = new SecurityLevel()
            {
                Level = lowestInputLevel, Name = "P'"
            };
            var poRewriter = new PhpChannelRewriter(new TreeContext(poAst), poComposer, provider, poNodesFactory, policy, collector.InputChannels, collector.OutputChannels, collector.SanitizeChannels, po.SecurityLevel, isOriginalProgram: true);

            poRewriter.VisitElement(poAst);
            po.Code = poComposer.Code.ToString();
            result.CodeTransformations.Add(po);

            return(result);
        }