Skip to content

Commit 0dfc68e

Browse files
authored
Merge pull request #1479 from WebFuzzing/fix/more-types
Add support for special characters
2 parents aabbbed + b10bbe3 commit 0dfc68e

File tree

6 files changed

+264
-85
lines changed

6 files changed

+264
-85
lines changed

core/src/main/kotlin/org/evomaster/core/solver/SMTConditionVisitor.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.evomaster.core.solver
22

33
import org.evomaster.client.java.controller.api.dto.database.schema.TableDto
4+
import org.evomaster.core.utils.StringUtils.convertToAscii
45
import org.evomaster.dbconstraint.ast.*
56
import org.evomaster.solver.smtlib.AssertSMTNode
67
import org.evomaster.solver.smtlib.EmptySMTNode
@@ -26,12 +27,18 @@ class SMTConditionVisitor(
2627
/**
2728
* Constructs a column reference string for SMT-LIB from a table name and column name.
2829
*
30+
* Both names are converted to ASCII because SMT-LIB unquoted symbols only allow ASCII characters.
31+
* Table and column names may come directly from SQL query text (e.g., a WHERE clause), which can
32+
* contain non-ASCII characters if the schema uses them. The conversion must happen here because,
33+
* unlike schema-derived names that are pre-converted via [SmtTable], query-derived names are
34+
* parsed at runtime from raw SQL strings.
35+
*
2936
* @param tableName The name of the table.
3037
* @param columnName The name of the column.
3138
* @return The SMT-LIB column reference string.
3239
*/
3340
private fun getColumnReference(tableName: String, columnName: String): String {
34-
return "(${columnName.uppercase()} ${tableName.lowercase()}$rowIndex)"
41+
return "(${convertToAscii(columnName).uppercase()} ${convertToAscii(tableName).lowercase()}$rowIndex)"
3542
}
3643

3744
/**

core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import org.evomaster.core.search.gene.sql.SqlPrimaryKeyGene
2020
import org.evomaster.core.search.gene.string.StringGene
2121
import org.evomaster.core.sql.SqlAction
2222
import org.evomaster.core.sql.schema.*
23+
import org.evomaster.core.utils.StringUtils.convertToAscii
2324
import org.evomaster.solver.Z3DockerExecutor
2425
import org.evomaster.solver.smtlib.SMTLib
2526
import org.evomaster.solver.smtlib.value.*
@@ -152,37 +153,42 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver {
152153

153154
// Create the list of genes with the values
154155
val genes = mutableListOf<Gene>()
155-
for (columnName in columns.fields) {
156-
var gene: Gene = IntegerGene(columnName, 0)
157-
when (val columnValue = columns.getField(columnName)) {
156+
// smtColumn is the Ascii version from SmtLib; resolve back to original DB column name
157+
for (smtColumn in columns.fields) {
158+
val dbColumn = table.columns.firstOrNull {
159+
convertToAscii(it.name).equals(smtColumn, ignoreCase = true)
160+
}
161+
val dbColumnName = dbColumn?.name ?: smtColumn
162+
163+
var gene: Gene = IntegerGene(dbColumnName, 0)
164+
when (val columnValue = columns.getField(smtColumn)) {
158165
is StringValue -> {
159-
gene = if (hasColumnType(schemaDto, table, columnName, "BOOLEAN")) {
160-
BooleanGene(columnName, toBoolean(columnValue.value))
166+
gene = if (hasColumnType(schemaDto, table, dbColumnName, "BOOLEAN")) {
167+
BooleanGene(dbColumnName, toBoolean(columnValue.value))
161168
} else {
162-
StringGene(columnName, columnValue.value)
169+
StringGene(dbColumnName, columnValue.value)
163170
}
164171
}
165172
is LongValue -> {
166-
gene = if (hasColumnType(schemaDto, table, columnName, "TIMESTAMP")) {
173+
gene = if (hasColumnType(schemaDto, table, dbColumnName, "TIMESTAMP")) {
167174
val epochSeconds = columnValue.value.toLong()
168175
val localDateTime = LocalDateTime.ofInstant(
169176
Instant.ofEpochSecond(epochSeconds), ZoneOffset.UTC
170177
)
171178
val formatted = localDateTime.format(
172179
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
173180
)
174-
ImmutableDataHolderGene(columnName, formatted, inQuotes = true)
181+
ImmutableDataHolderGene(dbColumnName, formatted, inQuotes = true)
175182
} else {
176-
IntegerGene(columnName, columnValue.value.toInt())
183+
IntegerGene(dbColumnName, columnValue.value.toInt())
177184
}
178185
}
179186
is RealValue -> {
180-
gene = DoubleGene(columnName, columnValue.value)
187+
gene = DoubleGene(dbColumnName, columnValue.value)
181188
}
182189
}
183-
val currentColumn = table.columns.firstOrNull(){ it.name.equals(columnName, ignoreCase = true) }
184-
if (currentColumn != null && currentColumn.primaryKey) {
185-
gene = SqlPrimaryKeyGene(columnName, table.id, gene, actionId)
190+
if (dbColumn != null && dbColumn.primaryKey) {
191+
gene = SqlPrimaryKeyGene(dbColumnName, table.id, gene, actionId)
186192
}
187193
gene.markAllAsInitialized()
188194
genes.add(gene)

0 commit comments

Comments
 (0)