diff --git a/src/atlasViewer/atlasViewer.constantService.service.spec.ts b/src/atlasViewer/atlasViewer.constantService.service.spec.ts index 71c9ecd02371900c4e3403e024f9d6e9c648a153..72f7f4c3f146f2fef352a2a3e0c6daa3c91ea224 100644 --- a/src/atlasViewer/atlasViewer.constantService.service.spec.ts +++ b/src/atlasViewer/atlasViewer.constantService.service.spec.ts @@ -107,4 +107,26 @@ describe('encodeNumber/decodeToNumber', () => { expect(floatNums.map(v => v.toFixed(FLOAT_PRECISION))).toEqual(decodedNumber.map(n => n.toFixed(FLOAT_PRECISION))) }) + + it('poisoned hash should throw', () => { + const illegialCharacters = './\\?#!@#^%&*()+={}[]\'"\n\t;:' + for (let char of illegialCharacters.split('')) { + expect(function (){ + decodeToNumber(char) + }).toThrow() + } + }) + + it('poisoned hash can be caught', () => { + + const testArray = ['abc', './\\', 'Cde'] + const decodedNum = testArray.map(v => { + try { + return decodeToNumber(v) + } catch (e) { + return null + } + }).filter(v => !!v) + expect(decodedNum.length).toEqual(2) + }) }) \ No newline at end of file diff --git a/src/atlasViewer/atlasViewer.constantService.service.ts b/src/atlasViewer/atlasViewer.constantService.service.ts index 958026caa32850fd8fe5f87fbcb979ec2766db7f..e27ccf1ce4f3ae0b68d8bbb0e2adc70abe4ad740 100644 --- a/src/atlasViewer/atlasViewer.constantService.service.ts +++ b/src/atlasViewer/atlasViewer.constantService.service.ts @@ -312,8 +312,7 @@ const negString = '~' const encodeInt = (number: number) => { if (number % 1 !== 0) throw 'cannot encodeInt on a float. Ensure float flag is set' - if (isNaN(Number(number)) || number === null || number === Number.POSITIVE_INFINITY) - throw 'The input is not valid' + if (isNaN(Number(number)) || number === null || number === Number.POSITIVE_INFINITY) throw 'The input is not valid' let rixit // like 'digit', only in some non-decimal radix let residual @@ -370,7 +369,9 @@ const decodetoInt = (encodedString: string) => { _encodedString = encodedString } return (negFlag ? -1 : 1) * [..._encodedString].reduce((acc,curr) => { - return acc * 64 + cipher.indexOf(curr) + const index = cipher.indexOf(curr) + if (index < 0) throw new Error(`Poisoned b64 encoding ${encodedString}`) + return acc * 64 + index }, 0) } diff --git a/src/atlasViewer/atlasViewer.urlService.service.ts b/src/atlasViewer/atlasViewer.urlService.service.ts index 8506cf25f696ab09fbe69dd4647c8d650b5dc6de..3d22afaedce280615f7b4bb0807956e61256a36b 100644 --- a/src/atlasViewer/atlasViewer.urlService.service.ts +++ b/src/atlasViewer/atlasViewer.urlService.service.ts @@ -170,7 +170,16 @@ export class AtlasViewerURLService{ for (let ngId in json) { const val = json[ngId] - const labelIndicies = val.split(separator).map(n =>decodeToNumber(n)) + const labelIndicies = val.split(separator).map(n =>{ + try{ + return decodeToNumber(n) + } catch (e) { + /** + * TODO poisonsed encoded char, send error message + */ + return null + } + }).filter(v => !!v) for (let labelIndex of labelIndicies) { selectRegionIds.push(`${ngId}#${labelIndex}`) } @@ -208,22 +217,29 @@ export class AtlasViewerURLService{ const cViewerState = searchparams.get('cNavigation') if (cViewerState) { - const [ cO, cPO, cPZ, cP, cZ ] = cViewerState.split(`${separator}${separator}`) - const o = cO.split(separator).map(s => decodeToNumber(s, {float: true})) - const po = cPO.split(separator).map(s => decodeToNumber(s, {float: true})) - const pz = decodeToNumber(cPZ) - const p = cP.split(separator).map(s => decodeToNumber(s)) - const z = decodeToNumber(cZ) - this.store.dispatch({ - type : CHANGE_NAVIGATION, - navigation : { - orientation: o, - perspectiveOrientation: po, - perspectiveZoom: pz, - position: p, - zoom: z - } - }) + try { + const [ cO, cPO, cPZ, cP, cZ ] = cViewerState.split(`${separator}${separator}`) + const o = cO.split(separator).map(s => decodeToNumber(s, {float: true})) + const po = cPO.split(separator).map(s => decodeToNumber(s, {float: true})) + const pz = decodeToNumber(cPZ) + const p = cP.split(separator).map(s => decodeToNumber(s)) + const z = decodeToNumber(cZ) + this.store.dispatch({ + type : CHANGE_NAVIGATION, + navigation : { + orientation: o, + perspectiveOrientation: po, + perspectiveZoom: pz, + position: p, + zoom: z + } + }) + } catch (e) { + /** + * TODO Poisoned encoded char + * send error message + */ + } } const niftiLayers = searchparams.get('niftiLayers')