commit 684d007983431abf7a0eb941a9588fb10302258e
parent 60c6b7a6d83f0b1b105f690c3e5243ac8768a2b3
Author: Jared Tobin <jared@jtobin.io>
Date: Sat, 3 Nov 2018 13:07:52 +1300
Add (weak) validation for @p and @q on conversion.
Functions like patp2hex and patq2hex will now throw on an invalid @p or
@q input. Note that these checks are not foolproof and only perform a
relatively weak validation, but one that should be sufficient for most
purposes.
Diffstat:
2 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/src/internal/co.js b/src/internal/co.js
@@ -52,6 +52,9 @@ remlysfynwerrycsugnysnyllyndyndemluxfedsedbecmun\
lyrtesmudnytbyrsenwegfyrmurtelreptegpecnelnevfes\
`
+const patp2syls = name =>
+ name.replace(/[\^~-]/g,'').match(/.{1,3}/g)
+
const splitAt = (index, str) => [str.slice(0, index), str.slice(index)]
const prefixes = pre.match(/.{1,3}/g)
@@ -129,14 +132,16 @@ const hex2patp = (hex) =>
* @return {String}
*/
const patp2hex = (name) => {
- const arr =
- name.replace(/[\^~-]/g,'').match(/.{1,3}/g)
+ if (isValidPat(name) === false) {
+ throw new Error('patp2hex: not a valid @p')
+ }
+ const syls = patp2syls(name)
const syl2bin = idx =>
idx.toString(2).padStart(8, '0')
- const addr = lodash.reduce(arr, (acc, syl, idx) =>
- idx % 2 !== 0 || arr.length === 1
+ const addr = lodash.reduce(syls, (acc, syl, idx) =>
+ idx % 2 !== 0 || syls.length === 1
? acc + syl2bin(suffixes.indexOf(syl))
: acc + syl2bin(prefixes.indexOf(syl)),
'')
@@ -215,8 +220,11 @@ const hex2patq = hex =>
* @param {String} name @q
* @return {String}
*/
-const patq2hex = str => {
- const chunks = lodash.split(str.slice(1), '-')
+const patq2hex = name => {
+ if (isValidPat(name) === false) {
+ throw new Error('patq2hex: not a valid @q')
+ }
+ const chunks = lodash.split(name.slice(1), '-')
const dec2hex = dec =>
dec.toString(16).padStart(2, '0')
@@ -228,7 +236,7 @@ const patq2hex = str => {
dec2hex(suffixes.indexOf(syls[1]))
})
- return str.length === 0
+ return name.length === 0
? '00'
: splat.join('')
}
@@ -271,7 +279,6 @@ const clan = who => {
: 'comet'
}
-
/**
* Determine the parent of a @p value.
*
@@ -294,6 +301,33 @@ const sein = (name) => {
return patp(res)
}
+/**
+ * Weakly check if a string is a valid @p or @q value.
+ *
+ * This is, at present, a pretty weak internal sanity check. It doesn't
+ * confirm the structure precisely (e.g. dashes), and for @q, it's required
+ * that q values of (greater than one) odd bytelength have been zero-padded.
+ * So, for example, '~doznec-binwod' will be considered a valid @q, but
+ * '~nec-binwod' will not.
+ *
+ * @param {String} name a @p or @q value
+ * @return {String}
+ */
+const isValidPat = name => {
+ const syls = patp2syls(name)
+
+ const leadingTilde = name.slice(0, 1) === '~'
+ const wrongLength = syls.length % 2 !== 0 && syls.length !== 1
+ const sylsExist = lodash.reduce(syls, (acc, syl, index) =>
+ acc &&
+ (index % 2 !== 0 || syls.length === 1
+ ? suffixes.includes(syl)
+ : prefixes.includes(syl)),
+ true)
+
+ return leadingTilde && !wrongLength && sylsExist
+}
+
module.exports = {
patp,
patp2hex,
diff --git a/test/co.test.js b/test/co.test.js
@@ -48,6 +48,17 @@ describe('patp, etc.', () => {
.to.equal('~divmes-davset-holdet--sallun-salpel-taswet-holtex--watmeb-tarlun-picdet-magmes--holter-dacruc-timdet-divtud--holwet-maldut-padpel-sivtud')
})
+ it('patp2hex throws on invalid patp', () => {
+ let input = () => patp2hex('nidsut-tomdun')
+ expect(input).to.throw()
+ input = () => patp2hex('~nidsut-tomdzn')
+ expect(input).to.throw()
+ input = () => patp2hex('~sut-tomdun')
+ expect(input).to.throw()
+ input = () => patp2hex('~nidsut-dun')
+ expect(input).to.throw()
+ })
+
it('patp and patp2dec are inverses', () => {
let iso0 = jsc.forall(jsc.uint32, num =>
parseInt(patp2dec(patp(num))) === num
@@ -98,6 +109,17 @@ describe('patq, etc.', () => {
.to.equal('~tastud-holruc-sidwet-salpel-taswet-holdeg-paddec-davdut-holdut-davwex-balwet-divwen-holdet-holruc-taslun-salpel-holtux-dacwex-baltud')
})
+ it('patq2hex throws on invalid patp', () => {
+ let input = () => patq2hex('nidsut-tomdun')
+ expect(input).to.throw()
+ input = () => patq2hex('~nidsut-tomdzn')
+ expect(input).to.throw()
+ input = () => patq2hex('~sut-tomdun')
+ expect(input).to.throw()
+ input = () => patq2hex('~nidsut-dun')
+ expect(input).to.throw()
+ })
+
it('patq and patq2dec are inverses', () => {
let iso0 = jsc.forall(jsc.uint32, num =>
parseInt(patq2dec(patq(num))) === num