Skip to content

Commit ee81936

Browse files
sehropebrianc
authored andcommitted
Libpq connection string escaping (brianc#1285)
* Fix escaping of libpq connection string properties Fix handlings of libpq connection properties to properly escape single quotes and backslashes. Previously the values were surrounded in single quotes which handled whitespace within the property value, but internal single quotes and backslashes would cause invalid connection strings to be generated. * Update expected output in test to be quoted Update the expect host output in the connection parameter test to expect it to be surrounded by single quotes. * Add test for configs with quotes and backslashes
1 parent 4659d5d commit ee81936

File tree

2 files changed

+30
-9
lines changed

2 files changed

+30
-9
lines changed

lib/connection-parameters.js

+11-6
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,15 @@ var ConnectionParameters = function(config) {
6565
this.fallback_application_name = val('fallback_application_name', config, false);
6666
};
6767

68+
// Convert arg to a string, surround in single quotes, and escape single quotes and backslashes
69+
var quoteParamValue = function(value) {
70+
return "'" + ('' + value).replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'";
71+
};
72+
6873
var add = function(params, config, paramName) {
6974
var value = config[paramName];
7075
if(value) {
71-
params.push(paramName+"='"+value+"'");
76+
params.push(paramName + "=" + quoteParamValue(value));
7277
}
7378
};
7479

@@ -87,23 +92,23 @@ ConnectionParameters.prototype.getLibpqConnectionString = function(cb) {
8792
add(params, ssl, 'sslcert');
8893

8994
if(this.database) {
90-
params.push("dbname='" + this.database + "'");
95+
params.push("dbname=" + quoteParamValue(this.database));
9196
}
9297
if(this.replication) {
93-
params.push("replication='" + this.replication + "'");
98+
params.push("replication=" + quoteParamValue(this.replication));
9499
}
95100
if(this.host) {
96-
params.push("host=" + this.host);
101+
params.push("host=" + quoteParamValue(this.host));
97102
}
98103
if(this.isDomainSocket) {
99104
return cb(null, params.join(' '));
100105
}
101106
if(this.client_encoding) {
102-
params.push("client_encoding='" + this.client_encoding + "'");
107+
params.push("client_encoding=" + quoteParamValue(this.client_encoding));
103108
}
104109
dns.lookup(this.host, function(err, address) {
105110
if(err) return cb(err, null);
106-
params.push("hostaddr=" + address);
111+
params.push("hostaddr=" + quoteParamValue(address));
107112
return cb(null, params.join(' '));
108113
});
109114
};

test/unit/connection-parameters/creation-tests.js

+19-3
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ test('libpq connection string building', function() {
126126
checkForPart(parts, "user='brian'");
127127
checkForPart(parts, "password='xyz'");
128128
checkForPart(parts, "port='888'");
129-
checkForPart(parts, "hostaddr=127.0.0.1");
129+
checkForPart(parts, "hostaddr='127.0.0.1'");
130130
checkForPart(parts, "dbname='bam'");
131131
}));
132132
});
@@ -143,7 +143,7 @@ test('libpq connection string building', function() {
143143
assert.isNull(err);
144144
var parts = constring.split(" ");
145145
checkForPart(parts, "user='brian'");
146-
checkForPart(parts, "hostaddr=127.0.0.1");
146+
checkForPart(parts, "hostaddr='127.0.0.1'");
147147
}));
148148
});
149149

@@ -173,7 +173,23 @@ test('libpq connection string building', function() {
173173
assert.isNull(err);
174174
var parts = constring.split(" ");
175175
checkForPart(parts, "user='brian'");
176-
checkForPart(parts, "host=/tmp/");
176+
checkForPart(parts, "host='/tmp/'");
177+
}));
178+
});
179+
180+
test('config contains quotes and backslashes', function() {
181+
var config = {
182+
user: 'not\\brian',
183+
password: 'bad\'chars',
184+
port: 5432,
185+
host: '/tmp/'
186+
};
187+
var subject = new ConnectionParameters(config);
188+
subject.getLibpqConnectionString(assert.calls(function(err, constring) {
189+
assert.isNull(err);
190+
var parts = constring.split(" ");
191+
checkForPart(parts, "user='not\\\\brian'");
192+
checkForPart(parts, "password='bad\\'chars'");
177193
}));
178194
});
179195

0 commit comments

Comments
 (0)