Skip to content

Commit

Permalink
Merge branch 'master' into feat/integrate-with-builder
Browse files Browse the repository at this point in the history
  • Loading branch information
agusaldasoro authored Dec 14, 2024
2 parents 953409e + 41e3256 commit 3ffffc8
Show file tree
Hide file tree
Showing 65 changed files with 1,418 additions and 119 deletions.
31 changes: 17 additions & 14 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,23 @@ jobs:
path: core/target/evomaster.jar
retention-days: ${{env.retention-days}}
if-no-files-found: error
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: webfuzzing/evomaster
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build and push Docker
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

installer-for-windows:
needs: build-base
Expand Down Expand Up @@ -129,7 +146,6 @@ jobs:
runs-on: "ubuntu-latest"

steps:

- name: Download fat jar
uses: actions/download-artifact@v4
with:
Expand All @@ -146,19 +162,6 @@ jobs:
uses: actions/download-artifact@v4
with:
name: evomaster.msi


## Doesn't seem any longer maintained... plus usability issues
# - uses: "marvinpinto/action-automatic-releases@latest"
# with:
# repo_token: "${{ secrets.GITHUB_TOKEN }}"
# prerelease: false
# files: |
# evomaster.jar
# ${{env.installer-windows}}
# ${{env.installer-osx}}
# ${{env.installer-debian}}

- name: Release
uses: softprops/action-gh-release@v1
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,4 @@ Migrations/
*.DS_Store
/e2e-tests/emb-json/target/
/process_data/
/e2e-tests/spring-rest-multidb/target/
46 changes: 46 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
FROM amazoncorretto:21-alpine-jdk

COPY core/target/evomaster.jar .

ENTRYPOINT [ \
"java", \
"-Xmx4G", \
"-jar", "evomaster.jar", \
"--runningInDocker", "true" \
]


###################
###### NOTES ######
###################
# Build
# docker build -t webfuzzing/evomaster .
#
# Run
# docker run webfuzzing/evomaster <options>
#
# Publish (latest, otherwise tag with :TAG)
# docker login
# docker push webfuzzing/evomaster
#
# Example remote BB
# docker run -v "/$(pwd)/generated_tests":/generated_tests webfuzzing/evomaster --blackBox true --bbSwaggerUrl https://api.apis.guru/v2/openapi.yaml --outputFormat JAVA_JUNIT_4 --maxTime 10s --ratePerMinute 60
#
# Example local BB
# docker run -v "/$(pwd)/generated_tests":/generated_tests webfuzzing/evomaster --blackBox true --bbSwaggerUrl http://host.docker.internal:8080/v3/api-docs --maxTime 5s
#
# Example WB (NOT IMPLEMENTED YET)
# docker run -v "/$(pwd)/generated_tests":/generated_tests webfuzzing/evomaster --dockerLocalhost true
#
# Setting for existing em.yaml
# -v "/$(pwd)/em.yaml":/em.yaml
#
# Debugging
# docker run -it --entrypoint sh webfuzzing/evomaster
#
#
#
#
#
#
#
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,17 @@ __Known limitations__:
-->


### Use in Industry

Several enterprises use _EvoMaster_ to fuzz their Web APIs.
We do few academia-industry collaborations ([see more info here](docs/contribute.md)), where we help test engineers to apply _EvoMaster_ on their systems, as long as we can then report on such experience.
Example of Fortune 500 companies using _EvoMaster_ are:

* [Meituan](https://www.meituan.com): see [TOSEM'23](docs/publications/2023_tosem_rpc.pdf), [ASE'24](docs/publications/2024_ase.pdf).

* [Volkswagen](https://www.volkswagen.com): see [AUSE'24](docs/publications/2024_ause_vw.pdf), [ICST'25](docs/publications/2025_icst.pdf).


### Videos

![](docs/img/video-player-flaticon.png)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,11 @@ public final void stopSut() {

@Override
public final boolean isInstrumentationActivated() {
return instrumentation && serverController != null && serverController.isConnectionOn();
return instrumentation && isConnectedToServerController();
}

public final boolean isConnectedToServerController(){
return serverController != null && serverController.isConnectionOn();
}

@Override
Expand Down Expand Up @@ -499,6 +503,14 @@ public final void setExecutingAction(boolean executingAction){

@Override
public final void bootingSut(boolean bootingSut) {
if(bootingSut && !isConnectedToServerController()){
/*
we cannot connect to server before SUT is started... but, once started,
might already be too late to state that it is in booting phase.
so, the default should be "booting".
*/
return;
}
checkInstrumentation();
serverController.setBootingSut(bootingSut);
// sync on the local ExecutionTracer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ public Response runSut(SutRunDto dto, @Context HttpServletRequest httpServletReq
} else {
//TODO as starting should be blocking, need to check
//if initialized, and wait if not
noKillSwitch(() -> sutController.bootingSut(false));
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.evomaster.client.java.instrumentation.shared.*;
import org.evomaster.client.java.instrumentation.staticstate.ExecutionTracer;
import org.evomaster.client.java.instrumentation.shared.ReplacementType;
import org.evomaster.client.java.utils.SimpleLogger;

import java.lang.reflect.Field;
import java.util.Objects;
Expand Down Expand Up @@ -110,7 +111,10 @@ match the regex, and find() only requires
String anyPositionRegexMatch = RegexSharedUtils.handlePartialMatch(regex);
boolean patternMatchResult = PatternMatchingHelper.matches(anyPositionRegexMatch, substring, idTemplate);
boolean matcherFindResult = caller.find();
assert (patternMatchResult == matcherFindResult);
if(patternMatchResult != matcherFindResult){
//TODO we should analyze those cases, and fix them
SimpleLogger.uniqueWarn("Failed to handle regex in Matcher.find(): " + regex);
}
return matcherFindResult;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ public static void start(int port){
case BOOTING_SUT:
handleBootingSut();
sendCommand(Command.ACK);
break;
case BOOT_TIME_INFO:
handleBootTimeObjectiveInfo();
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ public class ObjectiveRecorder {
/**
* Specify whether the SUT is booting or not.
* Targets during booting time are treated specially.
*
* Note: the default MUST be true, as might not be possible to modify this
* setting before the SUT is already started
*/
private static volatile boolean isBooting = false;
private static volatile boolean isBooting = true;

/**
* Key -> the unique id of the coverage objective
Expand Down Expand Up @@ -101,6 +104,7 @@ public class ObjectiveRecorder {
* Reset all the static state in this class
*/
public static void reset(boolean alsoAtLoadTime) {

maxObjectiveCoverage.clear();
idMapping.clear();
reversedIdMapping.clear();
Expand All @@ -116,6 +120,7 @@ public static void reset(boolean alsoAtLoadTime) {
allTargets.clear();

bootTimeObjectiveInfo.reset();
isBooting = true;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import org.evomaster.client.java.instrumentation.shared.StringSpecializationInfo;
import org.evomaster.client.java.instrumentation.shared.TaintInputName;
import org.evomaster.client.java.instrumentation.staticstate.ExecutionTracer;
import org.evomaster.client.java.instrumentation.staticstate.ObjectiveRecorder;
import org.evomaster.client.java.instrumentation.staticstate.UnitsInfoRecorder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.*;
Expand All @@ -18,6 +20,16 @@

public class JacksonObjectMapperTest {

@BeforeEach
public void init(){
ObjectiveRecorder.reset(false);
ObjectiveRecorder.setBooting(false);
ExecutionTracer.reset();
// force the state as executing action
ExecutionTracer.setExecutingAction(true);
assertEquals(0 , ExecutionTracer.getNumberOfObjectives());
}

@Test
public void testReadValue() throws Throwable {
String json = "{\n\"count\": 10\n}";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public static void initClass(){
@BeforeEach
public void init(){
ObjectiveRecorder.reset(false);
ObjectiveRecorder.setBooting(false);
ExecutionTracer.reset();
// force the state as executing action
ExecutionTracer.setExecutingAction(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,8 @@ private static String getDefaultSchema(DatabaseType type) {
return "dbo";
case MARIADB:
case MYSQL:
throw new IllegalArgumentException("there is no default schema for " + type + ", and you must specify a db name here");
//there is no concept of schema for those databases
return null;
case POSTGRES:
return "public";
}
Expand All @@ -434,12 +435,11 @@ private static String getAllTableCommand(DatabaseType type, String schema) {
switch (type) {
// https://stackoverflow.com/questions/175415/how-do-i-get-list-of-all-tables-in-a-database-using-tsql, TABLE_CATALOG='"+dbname+"'"
case MS_SQL_SERVER:
// for MySQL, schema is dbname
case MYSQL:
case MARIADB:
case H2:
case POSTGRES:
if (schema.isEmpty())
if (schema == null || schema.isEmpty())
return command;
return command + " AND TABLE_SCHEMA='" + schema + "'";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public VariableDescriptor(String columnName) {
}

public VariableDescriptor(String columnName, String alias, String tableName) {
this.columnName = columnName.trim().toLowerCase();
this.columnName = (columnName==null || columnName.trim().isEmpty() ?
null : columnName.trim().toLowerCase());
this.alias = (alias == null || alias.trim().isEmpty() ?
this.columnName :
alias.trim().toLowerCase());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static Set<String> getDeletedTables(String delete){

Table table = stmt.getTable();
if(table != null){
set.add(table.getName());
set.add(table.getFullyQualifiedName());
} else {
//TODO need to handle special cases of multi-tables with JOINs
throw new IllegalArgumentException("Cannot handle delete: " + delete);
Expand Down Expand Up @@ -130,7 +130,7 @@ public static Map<String, Set<String>> getSelectReadDataFields(String select){
}

private static void handleTable(Map<String, Set<String>> map, Table table){
Set<String> columns = map.computeIfAbsent(table.getName(), k -> new HashSet<>());
Set<String> columns = map.computeIfAbsent(table.getFullyQualifiedName(), k -> new HashSet<>());
//TODO: should check actual fields... would likely need to pass SelectBody as input as well
if(! columns.contains("*")) {
columns.add("*");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,26 @@ public static SqlDistanceWithMetrics computeDistance(
QueryResult... data
) {

/**
* This is not an ideal solution, but it will remain this way until config.heuristicsForSQLAdvanced remains
* experimental and it does not replace the "Plain" SqlHeuristicsCalculator
*/
if (advancedHeuristics) {
return SqlHeuristicsCalculator.computeDistance(sqlCommand,schema,taintHandler,data);
}

if (data.length == 0 || Arrays.stream(data).allMatch(QueryResult::isEmpty)){
//if no data, we have no info whatsoever
return new SqlDistanceWithMetrics(Double.MAX_VALUE,0, false);
}

Statement stmt = SqlParserUtils.parseSqlCommand(sqlCommand);

Expression where = getWhere(stmt);
if (where == null) {
//no constraint and at least one data point
return new SqlDistanceWithMetrics(0.0,0, false);
}


SqlNameContext context = new SqlNameContext(stmt);
if (schema != null) {
context.setSchema(schema);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.evomaster.client.java.sql.internal;

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.FromItem;
import org.evomaster.client.java.controller.api.dto.database.schema.DbInfoDto;
import org.evomaster.client.java.sql.QueryResult;

import static org.evomaster.client.java.sql.internal.SqlParserUtils.getFrom;
import static org.evomaster.client.java.sql.internal.SqlParserUtils.getWhere;

public class SqlHeuristicsCalculator {

public static SqlDistanceWithMetrics computeDistance(String sqlCommand,
DbInfoDto schema,
TaintHandler taintHandler,
QueryResult... data) {

Statement parsedSqlCommand = SqlParserUtils.parseSqlCommand(sqlCommand);
Expression whereClause= getWhere(parsedSqlCommand);
FromItem fromItem = getFrom(parsedSqlCommand);

if (fromItem == null && whereClause == null) {
return new SqlDistanceWithMetrics(0.0,0,false);
}


return null;
}
}
Loading

0 comments on commit 3ffffc8

Please sign in to comment.