Skip to content

Commit

Permalink
Security improvements.
Browse files Browse the repository at this point in the history
  • Loading branch information
bhvkshah authored and bsharifi committed May 14, 2024
1 parent 2e36f69 commit bc93694
Showing 1 changed file with 70 additions and 43 deletions.
113 changes: 70 additions & 43 deletions src/main/java/com/amazon/redshift/core/v3/SimpleParameterList.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,103 +184,130 @@ public void setNull(int index, int oid) throws SQLException {
bind(index, NULL_OBJECT, oid, binaryTransfer);
}

private static String quoteAndCast(String text, String type, boolean standardConformingStrings)
{
StringBuilder sb = new StringBuilder((text.length() + 10) / 10 * 11); // Add 10% for escaping.
sb.append("('");
try {
Utils.escapeLiteral(sb, text, standardConformingStrings);
} catch (SQLException e) {
// This should only happen if we have an embedded null
// and there's not much we can do if we do hit one.
//
// To force a server side failure, we deliberately include
// a zero byte character in the literal to force the server
// to reject the command.
sb.append('\u0000');
}
sb.append("'");
if (type != null) {
sb.append("::");
sb.append(type);
}
sb.append(")");
return sb.toString();
}

@Override
public String toString(int index, boolean standardConformingStrings) {
--index;
if (paramValues[index] == null) {
return "?";
} else if (paramValues[index] == NULL_OBJECT) {
return "NULL";
} else if ((flags[index] & BINARY) == BINARY) {
}
String textValue;
String type;
if ((flags[index] & BINARY) == BINARY) {
// handle some of the numeric types

switch (paramTypes[index]) {
case Oid.INT2:
short s = ByteConverter.int2((byte[]) paramValues[index], 0);
return Short.toString(s);
textValue = Short.toString(s);
type = "int2";
break;

case Oid.INT4:
int i = ByteConverter.int4((byte[]) paramValues[index], 0);
return Integer.toString(i);
textValue = Integer.toString(i);
type = "int4";
break;

case Oid.INT8:
long l = ByteConverter.int8((byte[]) paramValues[index], 0);
return Long.toString(l);
textValue = Long.toString(l);
type = "int8";
break;

case Oid.FLOAT4:
float f = ByteConverter.float4((byte[]) paramValues[index], 0);
if (Float.isNaN(f)) {
return "'NaN'::real";
}
return Float.toString(f);
textValue = Float.toString(f);
type = "real";
break;

case Oid.FLOAT8:
double d = ByteConverter.float8((byte[]) paramValues[index], 0);
if (Double.isNaN(d)) {
return "'NaN'::double precision";
}
return Double.toString(d);
textValue = Double.toString(d);
type = "double precision";
break;

case Oid.UUID:
String uuid =
textValue =
new UUIDArrayAssistant().buildElement((byte[]) paramValues[index], 0, 16).toString();
return "'" + uuid + "'::uuid";
type = "uuid";
break;

case Oid.POINT:
RedshiftPoint pgPoint = new RedshiftPoint();
pgPoint.setByteValue((byte[]) paramValues[index], 0);
return "'" + pgPoint.toString() + "'::point";
textValue = pgPoint.toString();
type = "point";
break;

case Oid.BOX:
RedshiftBox pgBox = new RedshiftBox();
pgBox.setByteValue((byte[]) paramValues[index], 0);
return "'" + pgBox.toString() + "'::box";
textValue = pgBox.toString();
type = "box";
break;

default:
return "?";
}
return "?";
} else {
String param = paramValues[index].toString();

// add room for quotes + potential escaping.
StringBuilder p = new StringBuilder(3 + (param.length() + 10) / 10 * 11);

// No E'..' here since escapeLiteral escapes all things and it does not use \123 kind of
// escape codes
p.append('\'');
try {
p = Utils.escapeLiteral(p, param, standardConformingStrings);
} catch (SQLException sqle) {
// This should only happen if we have an embedded null
// and there's not much we can do if we do hit one.
//
// The goal of toString isn't to be sent to the server,
// so we aren't 100% accurate (see StreamWrapper), put
// the unescaped version of the data.
//
p.append(param);
}
p.append('\'');
textValue = paramValues[index].toString();
int paramType = paramTypes[index];

if (paramType == Oid.TIMESTAMP) {
p.append("::timestamp");
type = "timestamp";
} else if (paramType == Oid.TIMESTAMPTZ) {
p.append("::timestamp with time zone");
type = "timestamp with time zone";
} else if (paramType == Oid.TIME) {
p.append("::time");
type = "time";
} else if (paramType == Oid.TIMETZ) {
p.append("::time with time zone");
type = "time with time zone";
} else if (paramType == Oid.DATE) {
p.append("::date");
type = "date";
} else if (paramType == Oid.INTERVAL) {
p.append("::interval");
type = "interval";
} else if (paramType == Oid.INTERVALY2M) {
p.append("::interval year to month");
type = "interval year to month";
} else if (paramType == Oid.INTERVALD2S) {
p.append("::interval day to second");
type = "interval day to second";
} else if (paramType == Oid.NUMERIC) {
p.append("::numeric");
type = "numeric";
}
else {
type = null;
}
return p.toString();
}
return quoteAndCast(textValue, type, standardConformingStrings);
}

@Override
Expand Down

0 comments on commit bc93694

Please sign in to comment.