mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-25 15:38:12 +08:00
protect against non-integer array indexing (#1595)
* do not assume non-iteger array bracket access will return undefined * revert to spec
This commit is contained in:
@@ -290,10 +290,8 @@ class Dataframe {
|
||||
|
||||
Use an existing accessor if provided, else compile a new one.
|
||||
*/
|
||||
const {
|
||||
getOffset: getRowByOffset,
|
||||
getLabel: getRowByLabel,
|
||||
} = this.rowIndex;
|
||||
const getRowByOffset = this.rowIndex.getOffset.bind(this.rowIndex);
|
||||
const getRowByLabel = this.rowIndex.getLabel.bind(this.rowIndex);
|
||||
this.__columnsAccessor = this.__columns.map((column, idx) => {
|
||||
if (accessors[idx]) {
|
||||
return accessors[idx];
|
||||
@@ -704,7 +702,9 @@ class Dataframe {
|
||||
/*
|
||||
Return column accessor by offset.
|
||||
*/
|
||||
return this.__columnsAccessor[columnOffset];
|
||||
return Number.isInteger(columnOffset)
|
||||
? this.__columnsAccessor[columnOffset]
|
||||
: undefined;
|
||||
}
|
||||
|
||||
at(r, c) {
|
||||
@@ -753,7 +753,14 @@ class Dataframe {
|
||||
dataframe - returns true/false
|
||||
*/
|
||||
const [nRows, nCols] = this.dims;
|
||||
return c >= 0 && c < nCols && r >= 0 && r < nRows;
|
||||
return (
|
||||
Number.isInteger(r) &&
|
||||
Number.isInteger(c) &&
|
||||
c >= 0 &&
|
||||
c < nCols &&
|
||||
r >= 0 &&
|
||||
r < nRows
|
||||
);
|
||||
}
|
||||
|
||||
hasCol(c) {
|
||||
|
||||
@@ -41,31 +41,29 @@ class IdentityInt32Index {
|
||||
return k;
|
||||
}
|
||||
|
||||
/* eslint-disable class-methods-use-this -- having these accessors as class methods allows for polymorphism */
|
||||
getOffset(i) {
|
||||
// label to offset
|
||||
return i;
|
||||
return Number.isInteger(i) && i >= 0 && i < this.maxOffset ? i : undefined;
|
||||
}
|
||||
|
||||
getOffsets(arr) {
|
||||
// labels to offsets
|
||||
return arr;
|
||||
return arr.map((i) => this.getOffset(i));
|
||||
}
|
||||
|
||||
getLabel(i) {
|
||||
// offset to label
|
||||
return i;
|
||||
return Number.isInteger(i) && i >= 0 && i < this.maxOffset ? i : undefined;
|
||||
}
|
||||
|
||||
getLabels(arr) {
|
||||
// offsets to labels
|
||||
return arr;
|
||||
return arr.map((i) => this.getLabel(i));
|
||||
}
|
||||
|
||||
size() {
|
||||
return this.maxOffset;
|
||||
}
|
||||
/* eslint-enable class-methods-use-this -- enable */
|
||||
|
||||
__promote(labelArray) {
|
||||
/*
|
||||
@@ -89,7 +87,7 @@ class IdentityInt32Index {
|
||||
const { maxOffset } = this;
|
||||
for (let i = 0, l = labels.length; i < l; i += 1) {
|
||||
const label = labels[i];
|
||||
if (label < 0 || label >= maxOffset)
|
||||
if (!Number.isInteger(label) || label < 0 || label >= maxOffset)
|
||||
throw new RangeError(`offset or label: ${label}`);
|
||||
}
|
||||
return this.__promote(labels);
|
||||
@@ -153,27 +151,21 @@ class DenseInt32Index {
|
||||
__compile() {
|
||||
const { minLabel, index, rindex } = this;
|
||||
this.getOffset = function getOffset(l) {
|
||||
return index[l - minLabel];
|
||||
if (!Number.isInteger(l)) return undefined;
|
||||
const offset = index[l - minLabel];
|
||||
return offset === -1 ? undefined : offset;
|
||||
};
|
||||
|
||||
this.getOffsets = function getOffsets(arr) {
|
||||
const res = new arr.constructor(arr.length);
|
||||
for (let i = 0, len = arr.length; i < len; i += 1) {
|
||||
res[i] = index[arr[i] - minLabel];
|
||||
}
|
||||
return res;
|
||||
return arr.map((i) => this.getOffset(i));
|
||||
};
|
||||
|
||||
this.getLabel = function getLabel(i) {
|
||||
return rindex[i];
|
||||
return Number.isInteger(i) ? rindex[i] : undefined;
|
||||
};
|
||||
|
||||
this.getLabels = function getLabels(arr) {
|
||||
const res = new arr.constructor(arr.length);
|
||||
for (let i = 0, len = arr.length; i < len; i += 1) {
|
||||
res[i] = rindex[arr[i]];
|
||||
}
|
||||
return res;
|
||||
return arr.map((i) => this.getLabel(i));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -275,23 +267,15 @@ class KeyIndex {
|
||||
};
|
||||
|
||||
this.getOffsets = function getOffsets(arr) {
|
||||
const res = new arr.constructor(arr.length);
|
||||
for (let i = 0, len = arr.length; i < len; i += 1) {
|
||||
res[i] = index.get(arr[i]);
|
||||
}
|
||||
return res;
|
||||
return arr.map((l) => this.getOffset(l));
|
||||
};
|
||||
|
||||
this.getLabel = function getLabel(i) {
|
||||
return rindex[i];
|
||||
return Number.isInteger(i) ? rindex[i] : undefined;
|
||||
};
|
||||
|
||||
this.getLabels = function getLabels(arr) {
|
||||
const res = new arr.constructor(arr.length);
|
||||
for (let i = 0, len = arr.length; i < len; i += 1) {
|
||||
res[i] = rindex[arr[i]];
|
||||
}
|
||||
return res;
|
||||
return arr.map((i) => this.getLabel(i));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -308,7 +292,9 @@ class KeyIndex {
|
||||
for (let i = 0, l = labels.length; i < l; i += 1) {
|
||||
const label = labels[i];
|
||||
const offset = this.getOffset(label);
|
||||
if (offset === undefined) throw new RangeError(`unknown label: ${label}`);
|
||||
if (offset === undefined || offset === -1) {
|
||||
throw new RangeError(`unknown label: ${label}`);
|
||||
}
|
||||
}
|
||||
|
||||
return new KeyIndex(labels);
|
||||
|
||||
Reference in New Issue
Block a user