From 599e13dda33cbe11dd77e1ec30dd9f33f4af63e0 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Fri, 18 Sep 2020 12:45:20 +0200 Subject: [PATCH] IDEMPIERE-4462 (#263) Integrate patch from Paul Bowden (Adaxa) Co-authored-by: Paul Bowden --- .../src/org/compiere/dbPort/Convert.java | 10 +++--- .../compiere/dbPort/Convert_PostgreSQL.java | 34 +++++++++++++++++-- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/org.adempiere.base/src/org/compiere/dbPort/Convert.java b/org.adempiere.base/src/org/compiere/dbPort/Convert.java index d11707da56..c8b238614f 100644 --- a/org.adempiere.base/src/org/compiere/dbPort/Convert.java +++ b/org.adempiere.base/src/org/compiere/dbPort/Convert.java @@ -293,13 +293,13 @@ public abstract class Convert * @param retVars * @return string */ - protected String replaceQuotedStrings(String inputValue, VectorretVars) { + protected String replaceQuotedStrings(String inputValue, VectorretVars, String nonce) { // save every value // Carlos Ruiz - globalqss - better matching regexp retVars.clear(); // First we need to replace double quotes to not be matched by regexp - Teo Sarca BF [3137355 ] - final String quoteMarker = "<--QUOTE"+System.currentTimeMillis()+"-->"; + final String quoteMarker = "<--QUOTE"+nonce+"-->"; inputValue = inputValue.replace("''", quoteMarker); Pattern p = Pattern.compile("'[[^']*]*'"); @@ -309,7 +309,7 @@ public abstract class Convert while (m.find()) { String var = inputValue.substring(m.start(), m.end()).replace(quoteMarker, "''"); // Put back quotes, if any retVars.addElement(var); - m.appendReplacement(retValue, "<--" + i + "-->"); + m.appendReplacement(retValue, "<--QS" + i + "QS" + nonce + "-->"); i++; } m.appendTail(retValue); @@ -324,12 +324,12 @@ public abstract class Convert * @param retVars * @return string */ - protected String recoverQuotedStrings(String retValue, VectorretVars) { + protected String recoverQuotedStrings(String retValue, VectorretVars, String nonce) { for (int i = 0; i < retVars.size(); i++) { //hengsin, special character in replacement can cause exception String replacement = (String) retVars.get(i); replacement = escapeQuotedString(replacement); - retValue = retValue.replace("<--" + i + "-->", replacement); + retValue = retValue.replace("<--QS" + i + "QS" + nonce + "-->", replacement); } return retValue; } diff --git a/org.compiere.db.postgresql.provider/src/org/compiere/dbPort/Convert_PostgreSQL.java b/org.compiere.db.postgresql.provider/src/org/compiere/dbPort/Convert_PostgreSQL.java index 21581a6482..e17961975a 100644 --- a/org.compiere.db.postgresql.provider/src/org/compiere/dbPort/Convert_PostgreSQL.java +++ b/org.compiere.db.postgresql.provider/src/org/compiere/dbPort/Convert_PostgreSQL.java @@ -19,6 +19,7 @@ import java.util.Map; import java.util.StringTokenizer; import java.util.TreeMap; import java.util.Vector; +import java.util.concurrent.ThreadLocalRandom; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -47,6 +48,8 @@ public class Convert_PostgreSQL extends Convert_SQL92 { private TreeMap m_map; + private String sharedNonce = generateNonce(); + /** Logger */ private static final CLogger log = CLogger.getCLogger(Convert_PostgreSQL.class); @@ -88,7 +91,15 @@ public class Convert_PostgreSQL extends Convert_SQL92 { /** Vector to save previous values of quoted strings **/ Vector retVars = new Vector(); - String statement = replaceQuotedStrings(sqlStatement, retVars); + String nonce = sharedNonce; + + // check for collision with nonce + while ( sqlStatement.contains(nonce)) + { + nonce = generateNonce(); + } + + String statement = replaceQuotedStrings(sqlStatement, retVars, nonce); statement = convertWithConvertMap(statement); statement = convertSimilarTo(statement); statement = DB_PostgreSQL.removeNativeKeyworkMarker(statement); @@ -106,7 +117,7 @@ public class Convert_PostgreSQL extends Convert_SQL92 { else if (isCreate && cmpString.indexOf(" VIEW ") != -1) ; else if (cmpString.indexOf("ALTER TABLE") != -1) { - statement = recoverQuotedStrings(statement, retVars); + statement = recoverQuotedStrings(statement, retVars, nonce); retVars.clear(); statement = convertDDL(convertComplexStatement(statement)); /* @@ -124,7 +135,7 @@ public class Convert_PostgreSQL extends Convert_SQL92 { statement = convertComplexStatement(convertAlias(statement)); } if (retVars.size() > 0) - statement = recoverQuotedStrings(statement, retVars); + statement = recoverQuotedStrings(statement, retVars, nonce); result.add(statement); if ("true".equals(System.getProperty("org.idempiere.db.debug"))) { @@ -176,6 +187,20 @@ public class Convert_PostgreSQL extends Convert_SQL92 { return "Y".equals(Env.getContext(Env.getCtx(), "P|IsUseSimilarTo")); } + /** + * Generate fairly hard to guess numeric string + */ + private String generateNonce() { + + String newNonce = Long.toString(ThreadLocalRandom.current() + .nextLong(100000000000000000L, + 999999999999999999L)).intern(); + + sharedNonce = newNonce; + + return newNonce; + } + @Override protected String escapeQuotedString(String in) { @@ -921,6 +946,9 @@ public class Convert_PostgreSQL extends Convert_SQL92 { } if (token.startsWith("'") && token.endsWith("'")) return false; + // quoted string substitution marker + else if ( token.matches("QS\\d+QS\\d{18}") ) + return false; else { try {