Fix insane bug where some profiles cause client hang
Some code was converting the customs object to an array with millions of elements, which caused iteration and ipc transport (json serialize) to hang the client for many minutes at a time. This is probably because incorrect lodash functions were used on the customs. Lodash would convert it to array and then it would get stored and turn up as array every time, corrupting storage and ensuring client denial of service. This fixes that bug by avoiding using incorrect lodash functions that convert things to arrays with millions of elements. It also retroactively fixes profiles that were stored with array customs, so the client won't crash.
This commit is contained in:
parent
b8e6d7fb09
commit
c539dba6a8
|
@ -213,7 +213,7 @@ export default class CharacterPreview extends Vue {
|
|||
updateCustoms(): void {
|
||||
this.customs = _.orderBy(
|
||||
_.map(
|
||||
_.reject(this.character!.character.customs || [], (c) => _.isUndefined(c)) as CustomKink[],
|
||||
_.reject(Object.values(this.character!.character.customs ?? []), (c) => _.isUndefined(c)) as CustomKink[],
|
||||
(c: CustomKink) => _.assign(
|
||||
{},
|
||||
c,
|
||||
|
|
|
@ -337,9 +337,9 @@ export class Matcher {
|
|||
return _.map(
|
||||
speciesOptions,
|
||||
(species) => {
|
||||
const nc = _.cloneDeep(c);
|
||||
|
||||
nc.infotags[TagId.Species] = { string: species };
|
||||
// Avoid _.cloneDeep because it chokes on array-like objects with very large keys
|
||||
// _.cloneDeep will happily make arrays with 41 million elements
|
||||
const nc = {...c, infotags: {...c.infotags, [TagId.Species]: {string: species}}};
|
||||
|
||||
return { character: nc, analysis: new CharacterAnalysis(nc) };
|
||||
}
|
||||
|
@ -975,18 +975,14 @@ export class Matcher {
|
|||
private getAllStandardKinks(c: Character): { [key: number]: KinkChoice } {
|
||||
const kinks = _.pickBy(c.kinks, _.isString);
|
||||
|
||||
_.each(
|
||||
c.customs,
|
||||
(custom: any) => {
|
||||
if (!custom) {
|
||||
return;
|
||||
// Avoid using _.forEach on c.customs because lodash thinks it is an array
|
||||
for (const custom of Object.values(c.customs)) {
|
||||
if (custom) {
|
||||
const children = (custom as any).children ?? {};
|
||||
|
||||
_.each(children, (child) => kinks[child] = custom.choice);
|
||||
}
|
||||
|
||||
const children = (custom.children) ? custom.children : {};
|
||||
|
||||
_.each(children, (child) => kinks[child] = custom.choice);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return kinks as any;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,22 @@ export class WorkerStore implements PermanentIndexedStore {
|
|||
|
||||
|
||||
async getProfile(name: string): Promise<ProfileRecord | undefined> {
|
||||
return this.workerClient.request('get', { name });
|
||||
const record: ProfileRecord | undefined = await this.workerClient.request('get', { name });
|
||||
|
||||
// fix custom kinks to prevent hangs
|
||||
|
||||
if (record && Array.isArray(record.profileData.character.customs)) {
|
||||
// fix customs because it will crash the client
|
||||
const customsObject: ProfileRecord['profileData']['character']['customs'] = {};
|
||||
|
||||
for (const [key, value] of Object.entries(record.profileData.character.customs)) {
|
||||
if (value !== undefined) customsObject[key] = value;
|
||||
}
|
||||
|
||||
record.profileData.character.customs = customsObject;
|
||||
}
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue