Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Malformed password argument leads to null pointer deference & segmentation fault #71

Merged
merged 2 commits into from May 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
85 changes: 85 additions & 0 deletions spec/keytar-spec.js
Expand Up @@ -9,6 +9,11 @@ describe("keytar", function() {
var account2 = 'buster2'
var password2 = 'secret2'

var object = {}
object.toString = function () {
throw new Error("Whoops! Time to seg fault")
}

beforeEach(async function() {
await keytar.deletePassword(service, account),
await keytar.deletePassword(service, account2)
Expand All @@ -34,6 +39,52 @@ describe("keytar", function() {
assert.equal(await keytar.getPassword(service, account), null)
})

describe("error handling", function () {
describe('setPassword', () => {
it("handles when an object is provided for service", async function () {
try {
await keytar.setPassword(object, account, password)
} catch (err) {
assert.equal(err.message, "Parameter 'service' must be a string")
}
})

it("handles when an object is provided for username", async function () {
try {
await keytar.setPassword(service, object, password)
} catch (err) {
assert.equal(err.message, "Parameter 'username' must be a string")
}
})

it("handles when an object is provided for password", async function () {
try {
await keytar.setPassword(service, account, object)
} catch (err) {
assert.equal(err.message, "Parameter 'password' must be a string")
}
})
})

describe('getPassword', () => {
it("handles when an object is provided for service", async function () {
try {
await keytar.getPassword(object, account)
} catch (err) {
assert.equal(err.message, "Parameter 'service' must be a string")
}
})

it("handles when an object is provided for username", async function () {
try {
await keytar.getPassword(service, object)
} catch (err) {
assert.equal(err.message, "Parameter 'username' must be a string")
}
})
})
})

describe("Unicode support", function() {
const service = "se庐vi\u00C7e"
const account = "shi\u0191\u2020ke\u00A5"
Expand All @@ -59,6 +110,24 @@ describe("keytar", function() {
it("yields false when the password didn't exist", async function() {
assert.equal(await keytar.deletePassword(service, account), false)
})

describe("error handling", function () {
it("handles when an object is provided for service", async function () {
try {
await keytar.deletePassword(object, account)
} catch (err) {
assert.equal(err.message, "Parameter 'service' must be a string")
}
})

it("handles when an object is provided for username", async function () {
try {
await keytar.deletePassword(service, object)
} catch (err) {
assert.equal(err.message, "Parameter 'username' must be a string")
}
})
})
})

describe("findPassword(service)", function() {
Expand All @@ -71,6 +140,14 @@ describe("keytar", function() {
it("yields null when no password can be found", async function() {
assert.equal(await keytar.findPassword(service), null)
})

it("handles when an object is provided for service", async function () {
try {
await keytar.findPassword(object)
} catch (err) {
assert.equal(err.message, "Parameter 'service' must be a string")
}
})
})

describe('findCredentials(service)', function() {
Expand All @@ -92,6 +169,14 @@ describe("keytar", function() {
assert.deepEqual([], accounts)
})

it("handles when an object is provided for service", async function () {
try {
await keytar.findCredentials(object)
} catch (err) {
assert.equal(err.message, "Parameter 'service' must be a string")
}
})

describe("Unicode support", function() {
const service = "se庐vi\u00C7e"
const account = "shi\u0191\u2020ke\u00A5"
Expand Down
49 changes: 49 additions & 0 deletions src/main.cc
Expand Up @@ -4,10 +4,27 @@
namespace {

NAN_METHOD(SetPassword) {
if (!info[0]->IsString()) {
Nan::ThrowTypeError("Parameter 'service' must be a string");
return;
}

Nan::Utf8String serviceNan(info[0]);
std::string service(*serviceNan, serviceNan.length());

if (!info[1]->IsString()) {
Nan::ThrowTypeError("Parameter 'username' must be a string");
return;
}

Nan::Utf8String usernameNan(info[1]);
std::string username(*usernameNan, usernameNan.length());

if (!info[2]->IsString()) {
Nan::ThrowTypeError("Parameter 'password' must be a string");
return;
}

Nan::Utf8String passwordNan(info[2]);
std::string password(*passwordNan, passwordNan.length());

Expand All @@ -20,8 +37,19 @@ NAN_METHOD(SetPassword) {
}

NAN_METHOD(GetPassword) {
if (!info[0]->IsString()) {
Nan::ThrowTypeError("Parameter 'service' must be a string");
return;
}

Nan::Utf8String serviceNan(info[0]);
std::string service(*serviceNan, serviceNan.length());

if (!info[1]->IsString()) {
Nan::ThrowTypeError("Parameter 'username' must be a string");
return;
}

Nan::Utf8String usernameNan(info[1]);
std::string username(*usernameNan, usernameNan.length());

Expand All @@ -33,8 +61,19 @@ NAN_METHOD(GetPassword) {
}

NAN_METHOD(DeletePassword) {
if (!info[0]->IsString()) {
Nan::ThrowTypeError("Parameter 'service' must be a string");
return;
}

Nan::Utf8String serviceNan(info[0]);
std::string service(*serviceNan, serviceNan.length());

if (!info[1]->IsString()) {
Nan::ThrowTypeError("Parameter 'username' must be a string");
return;
}

Nan::Utf8String usernameNan(info[1]);
std::string username(*usernameNan, usernameNan.length());

Expand All @@ -46,6 +85,11 @@ NAN_METHOD(DeletePassword) {
}

NAN_METHOD(FindPassword) {
if (!info[0]->IsString()) {
Nan::ThrowTypeError("Parameter 'service' must be a string");
return;
}

Nan::Utf8String serviceNan(info[0]);
std::string service(*serviceNan, serviceNan.length());

Expand All @@ -56,6 +100,11 @@ NAN_METHOD(FindPassword) {
}

NAN_METHOD(FindCredentials) {
if (!info[0]->IsString()) {
Nan::ThrowTypeError("Parameter 'service' must be a string");
return;
}

Nan::Utf8String serviceNan(info[0]);
std::string service(*serviceNan, serviceNan.length());

Expand Down