Skip to content

Commit 0ba80e9

Browse files
committed
Fix SIGBUS crash in wechat_qrcode during process shutdown
Fixes opencv/opencv#27971 Problem: Double-free crash in std::vector<zxing::Ref<zxing::qrcode::Version>>::~vector() during process shutdown when using wechat_qrcode module. The crash occurred with error "free(): double free detected in tcache 2" and SIGBUS signal. Root Cause: Static member variable VERSIONS was destroyed during shutdown while Ref<Version> objects still held references, causing double-free due to static initialization order fiasco. Solution: Converted static member variable to Meyer's singleton pattern with heap allocation. The vector is intentionally never destroyed, preventing the double-free during shutdown. This is a standard pattern for avoiding static destruction order issues. Changes: - version.hpp: Changed VERSIONS declaration to getVersions() function - version.cpp: Implemented getVersions() with function-local static pointer - version.cpp: Updated all 15+ references to use getVersions() instead of VERSIONS Testing: - Existing tests pass without crashes - No SIGBUS crash on shutdown - Small intentional memory "leak" (singleton pattern) is acceptable
1 parent 1d306fc commit 0ba80e9

File tree

2 files changed

+49
-45
lines changed

2 files changed

+49
-45
lines changed

modules/wechat_qrcode/src/zxing/qrcode/version.cpp

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,12 @@ unsigned int Version::VERSION_DECODE_INFO[] = {
4949
0x228BA, 0x2379F, 0x24B0B, 0x2542E, 0x26A64, 0x27541, 0x28C69};
5050
int Version::N_VERSION_DECODE_INFOS = 34;
5151

52-
vector<Ref<Version> > Version::VERSIONS;
53-
static int N_VERSIONS = Version::buildVersions();
52+
std::vector<Ref<Version> >& Version::getVersions() {
53+
static std::vector<Ref<Version> >* versions = new std::vector<Ref<Version> >();
54+
static int initialized = buildVersions();
55+
(void)initialized;
56+
return *versions;
57+
}
5458

5559
int Version::getVersionNumber() { return versionNumber_; }
5660

@@ -101,7 +105,7 @@ Version *Version::getVersionForNumber(int versionNumber, ErrorHandler &err_handl
101105
err_handler = zxing::ReaderErrorHandler("versionNumber must be between 1 and 40");
102106
return NULL;
103107
}
104-
return VERSIONS[versionNumber - 1];
108+
return getVersions()[versionNumber - 1];
105109
}
106110

107111
Version::Version(int versionNumber, vector<int> *alignmentPatternCenters, ECBlocks *ecBlocks1,
@@ -295,205 +299,205 @@ Ref<BitMatrix> Version::buildFunctionPattern(ErrorHandler &err_handler) {
295299
}
296300

297301
int Version::buildVersions() {
298-
VERSIONS.push_back(Ref<Version>(new Version(
302+
getVersions().push_back(Ref<Version>(new Version(
299303
1, intArray(0), new ECBlocks(7, new ECB(1, 19)), new ECBlocks(10, new ECB(1, 16)),
300304
new ECBlocks(13, new ECB(1, 13)), new ECBlocks(17, new ECB(1, 9)))));
301-
VERSIONS.push_back(Ref<Version>(new Version(
305+
getVersions().push_back(Ref<Version>(new Version(
302306
2, intArray(2, 6, 18), new ECBlocks(10, new ECB(1, 34)), new ECBlocks(16, new ECB(1, 28)),
303307
new ECBlocks(22, new ECB(1, 22)), new ECBlocks(28, new ECB(1, 16)))));
304-
VERSIONS.push_back(Ref<Version>(new Version(
308+
getVersions().push_back(Ref<Version>(new Version(
305309
3, intArray(2, 6, 22), new ECBlocks(15, new ECB(1, 55)), new ECBlocks(26, new ECB(1, 44)),
306310
new ECBlocks(18, new ECB(2, 17)), new ECBlocks(22, new ECB(2, 13)))));
307-
VERSIONS.push_back(Ref<Version>(new Version(
311+
getVersions().push_back(Ref<Version>(new Version(
308312
4, intArray(2, 6, 26), new ECBlocks(20, new ECB(1, 80)), new ECBlocks(18, new ECB(2, 32)),
309313
new ECBlocks(26, new ECB(2, 24)), new ECBlocks(16, new ECB(4, 9)))));
310-
VERSIONS.push_back(Ref<Version>(new Version(
314+
getVersions().push_back(Ref<Version>(new Version(
311315
5, intArray(2, 6, 30), new ECBlocks(26, new ECB(1, 108)), new ECBlocks(24, new ECB(2, 43)),
312316
new ECBlocks(18, new ECB(2, 15), new ECB(2, 16)),
313317
new ECBlocks(22, new ECB(2, 11), new ECB(2, 12)))));
314-
VERSIONS.push_back(Ref<Version>(new Version(
318+
getVersions().push_back(Ref<Version>(new Version(
315319
6, intArray(2, 6, 34), new ECBlocks(18, new ECB(2, 68)), new ECBlocks(16, new ECB(4, 27)),
316320
new ECBlocks(24, new ECB(4, 19)), new ECBlocks(28, new ECB(4, 15)))));
317-
VERSIONS.push_back(Ref<Version>(new Version(
321+
getVersions().push_back(Ref<Version>(new Version(
318322
7, intArray(3, 6, 22, 38), new ECBlocks(20, new ECB(2, 78)),
319323
new ECBlocks(18, new ECB(4, 31)), new ECBlocks(18, new ECB(2, 14), new ECB(4, 15)),
320324
new ECBlocks(26, new ECB(4, 13), new ECB(1, 14)))));
321-
VERSIONS.push_back(
325+
getVersions().push_back(
322326
Ref<Version>(new Version(8, intArray(3, 6, 24, 42), new ECBlocks(24, new ECB(2, 97)),
323327
new ECBlocks(22, new ECB(2, 38), new ECB(2, 39)),
324328
new ECBlocks(22, new ECB(4, 18), new ECB(2, 19)),
325329
new ECBlocks(26, new ECB(4, 14), new ECB(2, 15)))));
326-
VERSIONS.push_back(
330+
getVersions().push_back(
327331
Ref<Version>(new Version(9, intArray(3, 6, 26, 46), new ECBlocks(30, new ECB(2, 116)),
328332
new ECBlocks(22, new ECB(3, 36), new ECB(2, 37)),
329333
new ECBlocks(20, new ECB(4, 16), new ECB(4, 17)),
330334
new ECBlocks(24, new ECB(4, 12), new ECB(4, 13)))));
331-
VERSIONS.push_back(Ref<Version>(new Version(10, intArray(3, 6, 28, 50),
335+
getVersions().push_back(Ref<Version>(new Version(10, intArray(3, 6, 28, 50),
332336
new ECBlocks(18, new ECB(2, 68), new ECB(2, 69)),
333337
new ECBlocks(26, new ECB(4, 43), new ECB(1, 44)),
334338
new ECBlocks(24, new ECB(6, 19), new ECB(2, 20)),
335339
new ECBlocks(28, new ECB(6, 15), new ECB(2, 16)))));
336-
VERSIONS.push_back(
340+
getVersions().push_back(
337341
Ref<Version>(new Version(11, intArray(3, 6, 30, 54), new ECBlocks(20, new ECB(4, 81)),
338342
new ECBlocks(30, new ECB(1, 50), new ECB(4, 51)),
339343
new ECBlocks(28, new ECB(4, 22), new ECB(4, 23)),
340344
new ECBlocks(24, new ECB(3, 12), new ECB(8, 13)))));
341-
VERSIONS.push_back(Ref<Version>(new Version(12, intArray(3, 6, 32, 58),
345+
getVersions().push_back(Ref<Version>(new Version(12, intArray(3, 6, 32, 58),
342346
new ECBlocks(24, new ECB(2, 92), new ECB(2, 93)),
343347
new ECBlocks(22, new ECB(6, 36), new ECB(2, 37)),
344348
new ECBlocks(26, new ECB(4, 20), new ECB(6, 21)),
345349
new ECBlocks(28, new ECB(7, 14), new ECB(4, 15)))));
346-
VERSIONS.push_back(
350+
getVersions().push_back(
347351
Ref<Version>(new Version(13, intArray(3, 6, 34, 62), new ECBlocks(26, new ECB(4, 107)),
348352
new ECBlocks(22, new ECB(8, 37), new ECB(1, 38)),
349353
new ECBlocks(24, new ECB(8, 20), new ECB(4, 21)),
350354
new ECBlocks(22, new ECB(12, 11), new ECB(4, 12)))));
351-
VERSIONS.push_back(Ref<Version>(new Version(
355+
getVersions().push_back(Ref<Version>(new Version(
352356
14, intArray(4, 6, 26, 46, 66), new ECBlocks(30, new ECB(3, 115), new ECB(1, 116)),
353357
new ECBlocks(24, new ECB(4, 40), new ECB(5, 41)),
354358
new ECBlocks(20, new ECB(11, 16), new ECB(5, 17)),
355359
new ECBlocks(24, new ECB(11, 12), new ECB(5, 13)))));
356-
VERSIONS.push_back(Ref<Version>(new Version(
360+
getVersions().push_back(Ref<Version>(new Version(
357361
15, intArray(4, 6, 26, 48, 70), new ECBlocks(22, new ECB(5, 87), new ECB(1, 88)),
358362
new ECBlocks(24, new ECB(5, 41), new ECB(5, 42)),
359363
new ECBlocks(30, new ECB(5, 24), new ECB(7, 25)),
360364
new ECBlocks(24, new ECB(11, 12), new ECB(7, 13)))));
361-
VERSIONS.push_back(Ref<Version>(new Version(
365+
getVersions().push_back(Ref<Version>(new Version(
362366
16, intArray(4, 6, 26, 50, 74), new ECBlocks(24, new ECB(5, 98), new ECB(1, 99)),
363367
new ECBlocks(28, new ECB(7, 45), new ECB(3, 46)),
364368
new ECBlocks(24, new ECB(15, 19), new ECB(2, 20)),
365369
new ECBlocks(30, new ECB(3, 15), new ECB(13, 16)))));
366-
VERSIONS.push_back(Ref<Version>(new Version(
370+
getVersions().push_back(Ref<Version>(new Version(
367371
17, intArray(4, 6, 30, 54, 78), new ECBlocks(28, new ECB(1, 107), new ECB(5, 108)),
368372
new ECBlocks(28, new ECB(10, 46), new ECB(1, 47)),
369373
new ECBlocks(28, new ECB(1, 22), new ECB(15, 23)),
370374
new ECBlocks(28, new ECB(2, 14), new ECB(17, 15)))));
371-
VERSIONS.push_back(Ref<Version>(new Version(
375+
getVersions().push_back(Ref<Version>(new Version(
372376
18, intArray(4, 6, 30, 56, 82), new ECBlocks(30, new ECB(5, 120), new ECB(1, 121)),
373377
new ECBlocks(26, new ECB(9, 43), new ECB(4, 44)),
374378
new ECBlocks(28, new ECB(17, 22), new ECB(1, 23)),
375379
new ECBlocks(28, new ECB(2, 14), new ECB(19, 15)))));
376-
VERSIONS.push_back(Ref<Version>(new Version(
380+
getVersions().push_back(Ref<Version>(new Version(
377381
19, intArray(4, 6, 30, 58, 86), new ECBlocks(28, new ECB(3, 113), new ECB(4, 114)),
378382
new ECBlocks(26, new ECB(3, 44), new ECB(11, 45)),
379383
new ECBlocks(26, new ECB(17, 21), new ECB(4, 22)),
380384
new ECBlocks(26, new ECB(9, 13), new ECB(16, 14)))));
381-
VERSIONS.push_back(Ref<Version>(new Version(
385+
getVersions().push_back(Ref<Version>(new Version(
382386
20, intArray(4, 6, 34, 62, 90), new ECBlocks(28, new ECB(3, 107), new ECB(5, 108)),
383387
new ECBlocks(26, new ECB(3, 41), new ECB(13, 42)),
384388
new ECBlocks(30, new ECB(15, 24), new ECB(5, 25)),
385389
new ECBlocks(28, new ECB(15, 15), new ECB(10, 16)))));
386-
VERSIONS.push_back(Ref<Version>(new Version(
390+
getVersions().push_back(Ref<Version>(new Version(
387391
21, intArray(5, 6, 28, 50, 72, 94), new ECBlocks(28, new ECB(4, 116), new ECB(4, 117)),
388392
new ECBlocks(26, new ECB(17, 42)), new ECBlocks(28, new ECB(17, 22), new ECB(6, 23)),
389393
new ECBlocks(30, new ECB(19, 16), new ECB(6, 17)))));
390-
VERSIONS.push_back(Ref<Version>(new Version(
394+
getVersions().push_back(Ref<Version>(new Version(
391395
22, intArray(5, 6, 26, 50, 74, 98), new ECBlocks(28, new ECB(2, 111), new ECB(7, 112)),
392396
new ECBlocks(28, new ECB(17, 46)), new ECBlocks(30, new ECB(7, 24), new ECB(16, 25)),
393397
new ECBlocks(24, new ECB(34, 13)))));
394-
VERSIONS.push_back(Ref<Version>(new Version(
398+
getVersions().push_back(Ref<Version>(new Version(
395399
23, intArray(5, 6, 30, 54, 78, 102), new ECBlocks(30, new ECB(4, 121), new ECB(5, 122)),
396400
new ECBlocks(28, new ECB(4, 47), new ECB(14, 48)),
397401
new ECBlocks(30, new ECB(11, 24), new ECB(14, 25)),
398402
new ECBlocks(30, new ECB(16, 15), new ECB(14, 16)))));
399-
VERSIONS.push_back(Ref<Version>(new Version(
403+
getVersions().push_back(Ref<Version>(new Version(
400404
24, intArray(5, 6, 28, 54, 80, 106), new ECBlocks(30, new ECB(6, 117), new ECB(4, 118)),
401405
new ECBlocks(28, new ECB(6, 45), new ECB(14, 46)),
402406
new ECBlocks(30, new ECB(11, 24), new ECB(16, 25)),
403407
new ECBlocks(30, new ECB(30, 16), new ECB(2, 17)))));
404-
VERSIONS.push_back(Ref<Version>(new Version(
408+
getVersions().push_back(Ref<Version>(new Version(
405409
25, intArray(5, 6, 32, 58, 84, 110), new ECBlocks(26, new ECB(8, 106), new ECB(4, 107)),
406410
new ECBlocks(28, new ECB(8, 47), new ECB(13, 48)),
407411
new ECBlocks(30, new ECB(7, 24), new ECB(22, 25)),
408412
new ECBlocks(30, new ECB(22, 15), new ECB(13, 16)))));
409-
VERSIONS.push_back(Ref<Version>(new Version(
413+
getVersions().push_back(Ref<Version>(new Version(
410414
26, intArray(5, 6, 30, 58, 86, 114), new ECBlocks(28, new ECB(10, 114), new ECB(2, 115)),
411415
new ECBlocks(28, new ECB(19, 46), new ECB(4, 47)),
412416
new ECBlocks(28, new ECB(28, 22), new ECB(6, 23)),
413417
new ECBlocks(30, new ECB(33, 16), new ECB(4, 17)))));
414-
VERSIONS.push_back(Ref<Version>(new Version(
418+
getVersions().push_back(Ref<Version>(new Version(
415419
27, intArray(5, 6, 34, 62, 90, 118), new ECBlocks(30, new ECB(8, 122), new ECB(4, 123)),
416420
new ECBlocks(28, new ECB(22, 45), new ECB(3, 46)),
417421
new ECBlocks(30, new ECB(8, 23), new ECB(26, 24)),
418422
new ECBlocks(30, new ECB(12, 15), new ECB(28, 16)))));
419-
VERSIONS.push_back(
423+
getVersions().push_back(
420424
Ref<Version>(new Version(28, intArray(6, 6, 26, 50, 74, 98, 122),
421425
new ECBlocks(30, new ECB(3, 117), new ECB(10, 118)),
422426
new ECBlocks(28, new ECB(3, 45), new ECB(23, 46)),
423427
new ECBlocks(30, new ECB(4, 24), new ECB(31, 25)),
424428
new ECBlocks(30, new ECB(11, 15), new ECB(31, 16)))));
425-
VERSIONS.push_back(
429+
getVersions().push_back(
426430
Ref<Version>(new Version(29, intArray(6, 6, 30, 54, 78, 102, 126),
427431
new ECBlocks(30, new ECB(7, 116), new ECB(7, 117)),
428432
new ECBlocks(28, new ECB(21, 45), new ECB(7, 46)),
429433
new ECBlocks(30, new ECB(1, 23), new ECB(37, 24)),
430434
new ECBlocks(30, new ECB(19, 15), new ECB(26, 16)))));
431-
VERSIONS.push_back(
435+
getVersions().push_back(
432436
Ref<Version>(new Version(30, intArray(6, 6, 26, 52, 78, 104, 130),
433437
new ECBlocks(30, new ECB(5, 115), new ECB(10, 116)),
434438
new ECBlocks(28, new ECB(19, 47), new ECB(10, 48)),
435439
new ECBlocks(30, new ECB(15, 24), new ECB(25, 25)),
436440
new ECBlocks(30, new ECB(23, 15), new ECB(25, 16)))));
437-
VERSIONS.push_back(
441+
getVersions().push_back(
438442
Ref<Version>(new Version(31, intArray(6, 6, 30, 56, 82, 108, 134),
439443
new ECBlocks(30, new ECB(13, 115), new ECB(3, 116)),
440444
new ECBlocks(28, new ECB(2, 46), new ECB(29, 47)),
441445
new ECBlocks(30, new ECB(42, 24), new ECB(1, 25)),
442446
new ECBlocks(30, new ECB(23, 15), new ECB(28, 16)))));
443-
VERSIONS.push_back(Ref<Version>(
447+
getVersions().push_back(Ref<Version>(
444448
new Version(32, intArray(6, 6, 34, 60, 86, 112, 138), new ECBlocks(30, new ECB(17, 115)),
445449
new ECBlocks(28, new ECB(10, 46), new ECB(23, 47)),
446450
new ECBlocks(30, new ECB(10, 24), new ECB(35, 25)),
447451
new ECBlocks(30, new ECB(19, 15), new ECB(35, 16)))));
448-
VERSIONS.push_back(
452+
getVersions().push_back(
449453
Ref<Version>(new Version(33, intArray(6, 6, 30, 58, 86, 114, 142),
450454
new ECBlocks(30, new ECB(17, 115), new ECB(1, 116)),
451455
new ECBlocks(28, new ECB(14, 46), new ECB(21, 47)),
452456
new ECBlocks(30, new ECB(29, 24), new ECB(19, 25)),
453457
new ECBlocks(30, new ECB(11, 15), new ECB(46, 16)))));
454-
VERSIONS.push_back(
458+
getVersions().push_back(
455459
Ref<Version>(new Version(34, intArray(6, 6, 34, 62, 90, 118, 146),
456460
new ECBlocks(30, new ECB(13, 115), new ECB(6, 116)),
457461
new ECBlocks(28, new ECB(14, 46), new ECB(23, 47)),
458462
new ECBlocks(30, new ECB(44, 24), new ECB(7, 25)),
459463
new ECBlocks(30, new ECB(59, 16), new ECB(1, 17)))));
460-
VERSIONS.push_back(
464+
getVersions().push_back(
461465
Ref<Version>(new Version(35, intArray(7, 6, 30, 54, 78, 102, 126, 150),
462466
new ECBlocks(30, new ECB(12, 121), new ECB(7, 122)),
463467
new ECBlocks(28, new ECB(12, 47), new ECB(26, 48)),
464468
new ECBlocks(30, new ECB(39, 24), new ECB(14, 25)),
465469
new ECBlocks(30, new ECB(22, 15), new ECB(41, 16)))));
466-
VERSIONS.push_back(
470+
getVersions().push_back(
467471
Ref<Version>(new Version(36, intArray(7, 6, 24, 50, 76, 102, 128, 154),
468472
new ECBlocks(30, new ECB(6, 121), new ECB(14, 122)),
469473
new ECBlocks(28, new ECB(6, 47), new ECB(34, 48)),
470474
new ECBlocks(30, new ECB(46, 24), new ECB(10, 25)),
471475
new ECBlocks(30, new ECB(2, 15), new ECB(64, 16)))));
472-
VERSIONS.push_back(
476+
getVersions().push_back(
473477
Ref<Version>(new Version(37, intArray(7, 6, 28, 54, 80, 106, 132, 158),
474478
new ECBlocks(30, new ECB(17, 122), new ECB(4, 123)),
475479
new ECBlocks(28, new ECB(29, 46), new ECB(14, 47)),
476480
new ECBlocks(30, new ECB(49, 24), new ECB(10, 25)),
477481
new ECBlocks(30, new ECB(24, 15), new ECB(46, 16)))));
478-
VERSIONS.push_back(
482+
getVersions().push_back(
479483
Ref<Version>(new Version(38, intArray(7, 6, 32, 58, 84, 110, 136, 162),
480484
new ECBlocks(30, new ECB(4, 122), new ECB(18, 123)),
481485
new ECBlocks(28, new ECB(13, 46), new ECB(32, 47)),
482486
new ECBlocks(30, new ECB(48, 24), new ECB(14, 25)),
483487
new ECBlocks(30, new ECB(42, 15), new ECB(32, 16)))));
484-
VERSIONS.push_back(
488+
getVersions().push_back(
485489
Ref<Version>(new Version(39, intArray(7, 6, 26, 54, 82, 110, 138, 166),
486490
new ECBlocks(30, new ECB(20, 117), new ECB(4, 118)),
487491
new ECBlocks(28, new ECB(40, 47), new ECB(7, 48)),
488492
new ECBlocks(30, new ECB(43, 24), new ECB(22, 25)),
489493
new ECBlocks(30, new ECB(10, 15), new ECB(67, 16)))));
490-
VERSIONS.push_back(
494+
getVersions().push_back(
491495
Ref<Version>(new Version(40, intArray(7, 6, 30, 58, 86, 114, 142, 170),
492496
new ECBlocks(30, new ECB(19, 118), new ECB(6, 119)),
493497
new ECBlocks(28, new ECB(18, 47), new ECB(31, 48)),
494498
new ECBlocks(30, new ECB(34, 24), new ECB(34, 25)),
495499
new ECBlocks(30, new ECB(20, 15), new ECB(61, 16)))));
496-
return VERSIONS.size();
500+
return getVersions().size();
497501
}
498502

499503
} // namespace qrcode

modules/wechat_qrcode/src/zxing/qrcode/version.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class Version : public Counted {
6464
public:
6565
static unsigned int VERSION_DECODE_INFO[];
6666
static int N_VERSION_DECODE_INFOS;
67-
static std::vector<Ref<Version> > VERSIONS;
67+
static std::vector<Ref<Version> >& getVersions();
6868

6969
~Version();
7070
int getVersionNumber();

0 commit comments

Comments
 (0)