From 7e8517d08e9860ceede6c0833b4e37edabb11e65 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Wed, 3 Apr 2019 16:39:35 +0200 Subject: [PATCH] Add column limit support, similar to #541 --- lib/xlsx/xform/sheet/row-xform.js | 6 +++- lib/xlsx/xform/sheet/worksheet-xform.js | 3 +- spec/integration/data/many-columns.xlsx | Bin 0 -> 8885 bytes spec/integration/workbook-xlsx-reader.spec.js | 29 ++++++++++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 spec/integration/data/many-columns.xlsx diff --git a/lib/xlsx/xform/sheet/row-xform.js b/lib/xlsx/xform/sheet/row-xform.js index 27ec1bd48..9e08b8308 100644 --- a/lib/xlsx/xform/sheet/row-xform.js +++ b/lib/xlsx/xform/sheet/row-xform.js @@ -5,7 +5,8 @@ var BaseXform = require('../base-xform'); var CellXform = require('./cell-xform'); -var RowXform = module.exports = function() { +var RowXform = module.exports = function(options) { + this.maxItems = options && options.maxItems; this.map = { c: new CellXform() }; @@ -119,6 +120,9 @@ utils.inherits(RowXform, BaseXform, { if (this.parser) { if (!this.parser.parseClose(name)) { this.model.cells.push(this.parser.model); + if (this.maxItems && this.model.cells.length > this.maxItems) { + throw new Error('Max column count exceeded'); + } this.parser = undefined; } return true; diff --git a/lib/xlsx/xform/sheet/worksheet-xform.js b/lib/xlsx/xform/sheet/worksheet-xform.js index 50b3c0446..853b66e4d 100644 --- a/lib/xlsx/xform/sheet/worksheet-xform.js +++ b/lib/xlsx/xform/sheet/worksheet-xform.js @@ -30,13 +30,14 @@ var RowBreaksXform = require('./row-breaks-xform'); var WorkSheetXform = module.exports = function(options) { var maxRows = options && options.maxRows; + var maxCols = options && options.maxCols; this.map = { sheetPr: new SheetPropertiesXform(), dimension: new DimensionXform(), sheetViews: new ListXform({tag: 'sheetViews', count: false, childXform: new SheetViewXform()}), sheetFormatPr: new SheetFormatPropertiesXform(), cols: new ListXform({tag: 'cols', count: false, childXform: new ColXform()}), - sheetData: new ListXform({tag: 'sheetData', count: false, empty: true, childXform: new RowXform(), maxItems: maxRows}), + sheetData: new ListXform({tag: 'sheetData', count: false, empty: true, childXform: new RowXform({maxItems: maxCols}), maxItems: maxRows}), autoFilter: new AutoFilterXform(), mergeCells: new ListXform({tag: 'mergeCells', count: true, childXform: new MergeCellXform()}), rowBreaks: new RowBreaksXform(), diff --git a/spec/integration/data/many-columns.xlsx b/spec/integration/data/many-columns.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..c6c02482173e4e58a7b62e224f885ed04942b872 GIT binary patch literal 8885 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

irZPp~ibm<{hr;e9vSQj9(vD_|=$K|W z!A(BwTpb;DW~6r!0pMVlouTJ}Y32BF8`mDICIdE8O_5^)3GZkG!K&^blPxkkcp^%_ zj;b(I5UI?hwrB6M2`3lAT{NpK@KH<-fDmneSbyqf+L>^T-wqR6$0$0Hny6sPbG%n( zbtwh1)nnpJddWAfOuPZZwR5n3_{yoI+oaqXSy`zzSH;DGjIJ`ld*$Hvf?wpg^qE*+ z##cQzah6^AjH{c0`KC!LB#%I0@7MnPpVhZiC7qIJ7;eT$`Vx3e!1M9C(a1|p0?$|< z{TS_$7UZW{6NpV)u{49#v$1Q6Lfna74c?a9g%UjE$f|P zJ6PLb9SXq)gB6Xx5>~I=thN};_&OhAQ)b*&4`k^&xZ8zTRf{mdH!J6i?0pvuF)GnN z#PD7yA0-t&YNo-!oSk%3-Q`2AcB$1zwxhH3%hAn8N|YDMuO+$9x~F6|H`!o(W6=V* zv}>$+{KtgABxk%`9W%Ov2ki6Rq0~)gfD!2eHYWw*^D4W4$v)L zuGC(YLzIrZOyBq<)}wD~?J$RWYA#iT%s}W>BBL+1?>*-<%60MgC|h{c0^-%`?aqq*{O9E zxzmkHygp&tp@_(^QJr|jSLeUvjMX_w-kp-f%XxbP)?%X7?TNhvkJI5bzr3nHIwbAD z`?e$_&z~q6@v>H8X7wu@4n{;bMjz?a?5S6mgeQQ=DD298)D;ou!PAD%Tl9dQI})q) zpt~ct0X&4k4z<}{;ZM@>CY0Tn66Y(^Of=Vx>sM@BZ|b;+Mtt{?34-4TRn-KFl-Im| zb@L&*=xafxTw=W&Z%Ku6#!z9gzV#`h`%GIY@$|<)L%#AfM0b75W=kI8t{;!DBPOCx!bpP1Y8scN*n>N2-o*zGY~SMEu38 zy?1^1D)^DQn%ohhFI<*n_IRVJ`%b=(9-3C+>4Dcd^gHg;-rTyly3MHIj03?JLiorQMis4`&hon>5U`05;-JC$_Qq6P{66*nXI;Zq#-b^ zAMSPJr^5#Acmwg0PX@8F_hUdU4g*x*y{yA3GKT3u)?4vlQ=#PBrb-c&5g$LaX554I zqwfQsNEIZhMDVfu$n`+1ggN2Dgb6-&BnEn|EPaa+-4a-Jur<1jPOB}Hn(!Jux@Uc2 ztb#I^F^c!Dw@||WeS-KRR|H-_7YbYG1Ytw-gBDKasxD5iLG0#EE|&kQZ2d1S2t`g5 z#89P^k|^X*>Fx=}C9CVgL|hG+VrKGvGJnqTySBz?9R`@Hxz;3i{gPp{!vK&c|0c$@ z{pZ3h+~W9ZHq}%tyucsTvECY4o0GyV5^<-BXs;%TQLB)`tTr}ehA}p(LuB3wN?|@QPrQ#RXly zJT)!Cq~s4p#j`nlotk?!x7*Hixf!DTlt1yz2Un164Ra=lqHD1kRKdrq6wj?oNVBeT zyz6p2p%tCyXx$BySihX0Z_-k;Q9@w4@iAnAx)&~+%&a@zIMl0*F1+!c{ji?A&M+E| zR2na6R4O|D1hODj{3D+<&XqXcS+PPZb+kVLvRiv`O>sGw6$a;qeyp;Zj3fCh2j&=_ z0pxojFu)F-!M}sA!$=o7779KRD0i{`3_jD>um6WV=#>4dr9+gQ=6;qj;BF|;7f1vg z)X)Qq&0cDsm7Bpp+^v;AnP*qfh8M@}O{vt3PRzK^MpLjGiGIvKz|3IwRvBdlM5Z^!5S>>i0pP zQ3~LOZD$8ZxW6yI;cz1Jey?rm#eCeh1uSM?>sM8LSCsiURfTD_oRhTh+{&b+rE9Ag zX1HuZ<$JDp_R1}sy2RV)+=f3lXs@iPjalsuz5}KhM}!tFlWUnW4f5PQj(?kis#zV}muo?w*!?^m zxcQ}dbWkle7_?%-5xCwXusU2Jb+c$sc`O#51X_(VUCnr11GmHt8s-xfP`T;!A!|T> zNGAEbm3CfsM(VLbPP8=TWu!Srfb;ztNqJWkf5Lpx!X>!B0im_`#_-g`oIf~e`}_Hc zyP8qbwXro1omi>f^WXmgr#yWB literal 0 HcmV?d00001 diff --git a/spec/integration/workbook-xlsx-reader.spec.js b/spec/integration/workbook-xlsx-reader.spec.js index c57ca4943..b9c650df1 100644 --- a/spec/integration/workbook-xlsx-reader.spec.js +++ b/spec/integration/workbook-xlsx-reader.spec.js @@ -53,6 +53,35 @@ describe('WorkbookReader', function() { return workbook.xlsx.readFile('./spec/integration/data/fibonacci.xlsx', {maxRows: 20}); }); }); + + describe('Column limit', function() { + it('should bail out if the file contains more cells than the limit', function() { + const workbook = new Excel.Workbook(); + // The many-columns sheet has 20 columns in row 2 + return workbook.xlsx.readFile('./spec/integration/data/many-columns.xlsx', {maxCols: 15}) + .then(function() { + throw new Error('Promise unexpectedly fulfilled'); + }, function(err) { + expect(err.message).to.equal('Max column count exceeded'); + }); + }); + + it('should fail fast on a huge file', function() { + this.timeout(20000); + const workbook = new Excel.Workbook(); + return workbook.xlsx.readFile('./spec/integration/data/huge.xlsx', {maxCols: 10}) + .then(function() { + throw new Error('Promise unexpectedly fulfilled'); + }, function(err) { + expect(err.message).to.equal('Max column count exceeded'); + }); + }); + + it('should parse fine if the limit is not exceeded', function() { + const workbook = new Excel.Workbook(); + return workbook.xlsx.readFile('./spec/integration/data/many-columns.xlsx', {maxCols: 40}); + }); + }); }); describe('#read', function() {