From 5909601f77bc3a6e797bf3ba39c7a3c4fb562bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Holl=C3=A4nder?= Date: Tue, 20 Jul 2021 15:14:54 +0200 Subject: [PATCH] fix possible key duplication in ReferencesHandler (#188) fix #166 --- src/context/referenceshandler.ts | 9 ++++++--- src/nodes/use.ts | 5 ++--- test/common/tests.js | 1 + test/specs/duplicate-ids/reference.pdf | Bin 0 -> 4014 bytes test/specs/duplicate-ids/spec.svg | 9 +++++++++ 5 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 test/specs/duplicate-ids/reference.pdf create mode 100644 test/specs/duplicate-ids/spec.svg diff --git a/src/context/referenceshandler.ts b/src/context/referenceshandler.ts index 3ae20937..74398445 100644 --- a/src/context/referenceshandler.ts +++ b/src/context/referenceshandler.ts @@ -5,10 +5,13 @@ import { RGBColor } from '../utils/rgbcolor' export class ReferencesHandler { private readonly renderedElements: { [key: string]: SvgNode } private readonly idMap: { [id: string]: SvgNode } + private readonly idPrefix: string + private static instanceCounter = 0 constructor(idMap: { [id: string]: SvgNode }) { this.renderedElements = {} this.idMap = idMap + this.idPrefix = String(ReferencesHandler.instanceCounter++) } public async getRendered( @@ -16,7 +19,7 @@ export class ReferencesHandler { color: RGBColor | null, renderCallback: (node: SvgNode) => Promise ): Promise { - const key = ReferencesHandler.generateKey(id, color) + const key = this.generateKey(id, color) if (this.renderedElements.hasOwnProperty(key)) { return this.renderedElements[id] } @@ -33,7 +36,7 @@ export class ReferencesHandler { return this.idMap[cssEsc(id, { isIdentifier: true })] } - public static generateKey(id: string, color: RGBColor | null): string { - return id + '|' + (color || new RGBColor('rgb(0,0,0)')).toRGBA() + public generateKey(id: string, color: RGBColor | null): string { + return this.idPrefix + '|' + id + '|' + (color || new RGBColor('rgb(0,0,0)')).toRGBA() } } diff --git a/src/nodes/use.ts b/src/nodes/use.ts index d3c97045..2747088a 100644 --- a/src/nodes/use.ts +++ b/src/nodes/use.ts @@ -9,7 +9,6 @@ import { SvgNode } from './svgnode' import { Symbol } from './symbol' import { Viewport } from '../context/viewport' import { RGBColor } from '../utils/rgbcolor' -import { ReferencesHandler } from '../context/referenceshandler' /** * Draws the element referenced by a use node, makes use of pdf's XObjects/FormObjects so nodes are only written once @@ -86,7 +85,7 @@ export class Use extends GraphicsNode { context.pdf.clip().discardPath() } - context.pdf.doFormObject(ReferencesHandler.generateKey(id, color), t) + context.pdf.doFormObject(context.refsHandler.generateKey(id, color), t) context.pdf.restoreGraphicsState() } @@ -112,7 +111,7 @@ export class Use extends GraphicsNode { } else { await node.render(refContext) } - refContext.pdf.endFormObject(ReferencesHandler.generateKey(id, color)) + refContext.pdf.endFormObject(refContext.refsHandler.generateKey(id, color)) } protected getBoundingBoxCore(context: Context): number[] { diff --git a/test/common/tests.js b/test/common/tests.js index 9b0ce02b..d505b8b1 100644 --- a/test/common/tests.js +++ b/test/common/tests.js @@ -17,6 +17,7 @@ window.tests = [ 'complete-social-network', 'custom-fonts', 'display-none-and-visibility-inheritance', + 'duplicate-ids', 'empty-elements', 'fill-and-stroke-inheritance', 'fill-and-stroke-opacity', diff --git a/test/specs/duplicate-ids/reference.pdf b/test/specs/duplicate-ids/reference.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2026d4fe3a3314621659f6729e02f61f47c8d5a8 GIT binary patch literal 4014 zcmcIn?{3>R5dY4nxG%w446#JY@}I#75ZiHTw1qP}K#K+aAj^!SKo%2;Zj(LJo?tJt zK1%N>$yUsHc8ACosMG1lJKjJ3baFKuo$`jqPX7MqukXwQ7u5Wo^?J_r^MeHEDp*Q} zV=5C39N$ivGnJWIr=iS1$<{+Z_I^D_Q-exa9zC6T)G)G;i~#(BZ6$Cab^RS z`vmgEHpW6K*(a8u^doaFXB?Kl7#!vziGJ2M<(j+wIG z1!$1i8kCz=ju?i*(M3QgwpQdb=Dd#<8Qf4_Ou+ zf%8trU!{)1fH|}ET${Y2?BdM1NJ6!Uk|j8wqU1cuqLRU!QIuwSa2KTD3Cxk8co4o{ zQQkUU`DtIpi`TcH{Sy{U=5h46#(H{fH*|i&2y#PhhI9`aGQidm$@KMoz^V6?EhTSW zyNOunt|=4vwuJUoLTNy4{^!(@k9R_Sc5DxleZIJkRx&%Cs#TEGkPOxH<=>Mb*I!Rl z;D?)Hu70e8I0|dn|KY~C-G6OH9PW*O1P`}E?EmvX<5{!Y7LPgt_~GU^dtS{|{D0T4 z_Ovhn-auG$jtHc342f#*$z`?&q_F$K=gItDhImMBc05w)3eQXfqE3AT0cPMt(SRrK z$3UkMLaYtsC<%O5AgE5K0-y|x5d>p!4O*rF>2iyr%GrSUAs0Z*MCb#rIH$~GOm7S7 zj`b1SSkOV(O{cC6cK2@(ORl~hR=Vm{s=}GnaN{6!2IpEnA;cN45GVJG`=GdwF){`L z^?FEfpr(NEc_e_UlPC|UM2Knvr7=-HP{I+_LcbSe8_elK+zukeg4+ddfEjX8lIIv3 zX^uHlh@dPlwV^OC^`WpSoGCffxp>l-GaYCNWGbOwUKnvX6JWAC7cAmx#0c)1+(xSi zX__=JVwK#lo&)H)#X6KJyt&WFcf8>?+_zXw2>5lRk|7!JX80TLcG_HE&Y9n@uKNpK zZ>!~IclSYnom4I9Q)P)CCdHS^ + + + + + + + +