@@ -604,61 +604,107 @@ GPUd() uint32_t GPUTPCCFDecodeZSDenseLink::DecodePage(GPUSharedMemory& smem, pro
604604 const auto * decHeader = Peek<TPCZSHDRV2>(page, raw::RDHUtils::getMemorySize (*rawDataHeader) - sizeof (TPCZSHDRV2));
605605 ConsumeHeader<header::RAWDataHeader>(page);
606606
607- assert (decHeader->version >= ZSVersionDenseLinkBased);
608- assert (decHeader->magicWord == tpc::zerosupp_link_based::CommonHeader::MagicWordLinkZSMetaHeader);
609-
610607 uint16_t nSamplesWritten = 0 ;
611608 const uint16_t nSamplesInPage = decHeader->nADCsamples ;
612609
613610 const auto * payloadEnd = Peek (pageStart, raw::RDHUtils::getMemorySize (*rawDataHeader) - sizeof (TPCZSHDRV2) - ((decHeader->flags & TPCZSHDRV2::ZSFlags::TriggerWordPresent) ? TPCZSHDRV2::TRIGGER_WORD_SIZE : 0 ));
614611 const auto * nextPage = Peek (pageStart, TPCZSHDR::TPC_ZS_PAGE_SIZE);
615612
613+ const bool extendsToNextPage = decHeader->flags & TPCZSHDRV2::ZSFlags::payloadExtendsToNextPage;
614+
616615 ConsumeBytes (page, decHeader->firstZSDataOffset - sizeof (o2::header::RAWDataHeader));
617616
618- for ( uint16_t i = 0 ; i < decHeader-> nTimebinHeaders ; i++) {
617+ int err = GPUErrors::ERROR_NONE;
619618
620- [[maybe_unused]] ptrdiff_t sizeLeftInPage = payloadEnd - page;
621- assert (sizeLeftInPage > 0 );
619+ if (decHeader->version < ZSVersionDenseLinkBased) {
620+ err = GPUErrors::ERROR_TPCZS_VERSION_MISMATCH;
621+ }
622622
623- uint16_t nSamplesWrittenTB = 0 ;
623+ if (decHeader->magicWord != zerosupp_link_based::CommonHeader::MagicWordLinkZSMetaHeader) {
624+ err = GPUErrors::ERROR_TPCZS_INVALID_MAGIC_WORD;
625+ }
626+
627+ for (uint16_t i = 0 ; i < decHeader->nTimebinHeaders && !err; i++) {
628+
629+ ptrdiff_t sizeLeftInPage = payloadEnd - page;
630+ if (sizeLeftInPage <= 0 ) {
631+ err = GPUErrors::ERROR_TPCZS_PAGE_OVERFLOW;
632+ break ;
633+ }
634+
635+ int16_t nSamplesWrittenTB = 0 ;
636+ uint16_t nSamplesLeftInPage = nSamplesInPage - nSamplesWritten;
637+
638+ if (i == decHeader->nTimebinHeaders - 1 && extendsToNextPage) {
639+ if (raw::RDHUtils::getMemorySize (*rawDataHeader) != TPCZSHDR::TPC_ZS_PAGE_SIZE) {
640+ err = GPUErrors::ERROR_TPCZS_PAGE_OVERFLOW;
641+ break ;
642+ }
624643
625- if (i == decHeader->nTimebinHeaders - 1 && decHeader->flags & o2::tpc::TPCZSHDRV2::ZSFlags::payloadExtendsToNextPage) {
626- assert (o2::raw::RDHUtils::getMemorySize (*rawDataHeader) == TPCZSHDR::TPC_ZS_PAGE_SIZE);
627644 if ((uint16_t )(raw::RDHUtils::getPageCounter (rawDataHeader) + 1 ) == raw::RDHUtils::getPageCounter (nextPage)) {
628- nSamplesWrittenTB = DecodeTB<DecodeInParallel, true >(clusterer, smem, iThread, page, pageDigitOffset, rawDataHeader, firstHBF, decHeader->cruID , payloadEnd, nextPage);
645+ nSamplesWrittenTB = DecodeTB<DecodeInParallel, true >(clusterer, smem, iThread, page, pageDigitOffset, rawDataHeader, firstHBF, decHeader->cruID , nSamplesLeftInPage, payloadEnd, nextPage);
629646 } else {
630- nSamplesWrittenTB = FillWithInvalid (clusterer, iThread, nThreads, pageDigitOffset, nSamplesInPage - nSamplesWritten);
631- #ifdef GPUCA_CHECK_TPCZS_CORRUPTION
632- if (iThread == 0 ) {
633- clusterer.raiseError (GPUErrors::ERROR_TPCZS_INCOMPLETE_HBF, clusterer.mISector * 1000 + decHeader->cruID , raw::RDHUtils::getPageCounter (rawDataHeader), raw::RDHUtils::getPageCounter (nextPage));
634- }
635- #endif
647+ err = GPUErrors::ERROR_TPCZS_INCOMPLETE_HBF;
648+ break ;
636649 }
637650 } else {
638- nSamplesWrittenTB = DecodeTB<DecodeInParallel, false >(clusterer, smem, iThread, page, pageDigitOffset, rawDataHeader, firstHBF, decHeader->cruID , payloadEnd, nextPage);
651+ nSamplesWrittenTB = DecodeTB<DecodeInParallel, false >(clusterer, smem, iThread, page, pageDigitOffset, rawDataHeader, firstHBF, decHeader->cruID , nSamplesLeftInPage, payloadEnd, nextPage);
652+ }
653+
654+ // Abort decoding the page if an error was detected.
655+ if (nSamplesWrittenTB < 0 ) {
656+ err = -nSamplesWrittenTB;
657+ break ;
639658 }
640659
641- assert (nSamplesWritten <= nSamplesInPage);
642660 nSamplesWritten += nSamplesWrittenTB;
643661 pageDigitOffset += nSamplesWrittenTB;
644662 } // for (uint16_t i = 0; i < decHeader->nTimebinHeaders; i++)
645663
646- #ifdef GPUCA_CHECK_TPCZS_CORRUPTION
647- if (iThread == 0 && nSamplesWritten != nSamplesInPage) {
648- clusterer.raiseError (GPUErrors::ERROR_TPCZS_INVALID_NADC, clusterer.mISector * 1000 + decHeader->cruID , nSamplesInPage, nSamplesWritten);
649- /* #ifndef GPUCA_GPUCODE
650- FILE* foo = fopen("dump.bin", "w+b");
651- fwrite(pageSrc, 1, o2::raw::RDHUtils::getMemorySize(*rdHdr), foo);
652- fclose(foo);
653- #endif*/
664+ if (nSamplesWritten != nSamplesInPage) {
665+ if (nSamplesWritten < nSamplesInPage) {
666+ pageDigitOffset += FillWithInvalid (clusterer, iThread, nThreads, pageDigitOffset, nSamplesInPage - nSamplesWritten);
667+ }
668+ err = !err ? GPUErrors::ERROR_TPCZS_INVALID_NADC : err; // Ensure we don't overwrite any previous error
654669 }
670+
671+ if (iThread == 0 && err) {
672+ [[maybe_unused]] bool dumpPage = false ;
673+
674+ if (err == GPUErrors::ERROR_TPCZS_VERSION_MISMATCH) {
675+ clusterer.raiseError (err, decHeader->version , ZSVersionDenseLinkBased);
676+ } else if (err == GPUErrors::ERROR_TPCZS_INVALID_MAGIC_WORD) {
677+ clusterer.raiseError (err, decHeader->magicWord );
678+ } else if (err == GPUErrors::ERROR_TPCZS_INCOMPLETE_HBF) {
679+ clusterer.raiseError (err, clusterer.mISector * 1000 + decHeader->cruID , raw::RDHUtils::getPageCounter (rawDataHeader), raw::RDHUtils::getPageCounter (nextPage));
680+ } else if (err == GPUErrors::ERROR_TPCZS_PAGE_OVERFLOW) {
681+ clusterer.raiseError (err, extendsToNextPage);
682+ dumpPage = true ;
683+ } else if (err == GPUErrors::ERROR_TPCZS_INVALID_NADC) {
684+ clusterer.raiseError (err, nSamplesInPage, nSamplesWritten, extendsToNextPage);
685+ dumpPage = true ;
686+ } else {
687+ clusterer.raiseError (GPUErrors::ERROR_TPCZS_UNKNOWN, err);
688+ }
689+
690+ #ifdef GPUCA_CHECK_TPCZS_CORRUPTION
691+ #ifndef GPUCA_GPUCODE
692+ if (dumpPage) {
693+ // allocate more space on the stack for fname, so it can be overwritten by hand in a debugger.
694+ const char fname[64 ] = " dump00.bin" ;
695+ FILE* foo = fopen (fname, " w+b" );
696+ fwrite (pageStart, 1 , TPCZSHDR::TPC_ZS_PAGE_SIZE, foo);
697+ fclose (foo);
698+ }
699+ #endif
655700#endif
701+ }
656702
657703 return pageDigitOffset;
658704}
659705
660706template <bool DecodeInParallel, bool PayloadExtendsToNextPage>
661- GPUd () uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTB (
707+ GPUd () int16_t GPUTPCCFDecodeZSDenseLink::DecodeTB (
662708 processorType& clusterer,
663709 [[maybe_unused]] GPUSharedMemory& smem,
664710 int32_t iThread,
@@ -667,23 +713,24 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTB(
667713 const header::RAWDataHeader* rawDataHeader,
668714 int32_t firstHBF,
669715 int32_t cru,
670- [[maybe_unused]] const uint8_t * payloadEnd,
671- [[maybe_unused]] const uint8_t * nextPage)
716+ uint16_t nSamplesLeftInPage,
717+ const uint8_t * payloadEnd,
718+ const uint8_t * nextPage)
672719{
673720
674721 if constexpr (DecodeInParallel) {
675- return DecodeTBMultiThread<PayloadExtendsToNextPage>(clusterer, smem, iThread, page, pageDigitOffset, rawDataHeader, firstHBF, cru, payloadEnd, nextPage);
722+ return DecodeTBMultiThread<PayloadExtendsToNextPage>(clusterer, smem, iThread, page, pageDigitOffset, rawDataHeader, firstHBF, cru, nSamplesLeftInPage, payloadEnd, nextPage);
676723 } else {
677- uint16_t nSamplesWritten = 0 ;
724+ int16_t nSamplesWritten = 0 ;
678725 if (iThread == 0 ) {
679- nSamplesWritten = DecodeTBSingleThread<PayloadExtendsToNextPage>(clusterer, page, pageDigitOffset, rawDataHeader, firstHBF, cru, payloadEnd, nextPage);
726+ nSamplesWritten = DecodeTBSingleThread<PayloadExtendsToNextPage>(clusterer, page, pageDigitOffset, rawDataHeader, firstHBF, cru, nSamplesLeftInPage, payloadEnd, nextPage);
680727 }
681728 return warp_broadcast (nSamplesWritten, 0 );
682729 }
683730}
684731
685732template <bool PayloadExtendsToNextPage>
686- GPUd () uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBMultiThread (
733+ GPUd () int16_t GPUTPCCFDecodeZSDenseLink::DecodeTBMultiThread (
687734 processorType& clusterer,
688735 GPUSharedMemory& smem,
689736 const int32_t iThread,
@@ -692,8 +739,9 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBMultiThread(
692739 const header::RAWDataHeader* rawDataHeader,
693740 int32_t firstHBF,
694741 int32_t cru,
695- [[maybe_unused]] const uint8_t * payloadEnd,
696- [[maybe_unused]] const uint8_t * nextPage)
742+ uint16_t nSamplesLeftInPage,
743+ const uint8_t * payloadEnd,
744+ const uint8_t * nextPage)
697745{
698746#define MAYBE_PAGE_OVERFLOW (pagePtr ) \
699747 if constexpr (PayloadExtendsToNextPage) { \
@@ -703,7 +751,9 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBMultiThread(
703751 ConsumeBytes (pagePtr, sizeof (header::RAWDataHeader) + diff); \
704752 } \
705753 } else { \
706- assert (pagePtr <= payloadEnd); \
754+ if (pagePtr > payloadEnd) { \
755+ return -GPUErrors::ERROR_TPCZS_PAGE_OVERFLOW; \
756+ } \
707757 }
708758
709759#define PEEK_OVERFLOW (pagePtr, offset ) \
@@ -728,7 +778,7 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBMultiThread(
728778 uint16_t linkBC = (tbbHdr & 0xFFF0 ) >> 4 ;
729779 int32_t timeBin = (linkBC + (uint64_t )(raw::RDHUtils::getHeartBeatOrbit (*rawDataHeader) - firstHBF) * constants::lhc::LHCMaxBunches) / LHCBCPERTIMEBIN;
730780
731- uint16_t nSamplesInTB = 0 ;
781+ int16_t nSamplesInTB = 0 ;
732782
733783 // Read timebin link headers
734784 for (uint8_t iLink = 0 ; iLink < nLinksInTimebin; iLink++) {
@@ -747,7 +797,6 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBMultiThread(
747797 }
748798
749799 int32_t nBytesBitmask = CAMath::Popcount (bitmaskL2);
750- assert (nBytesBitmask <= 10 );
751800
752801 for (int32_t chan = iThread; chan < CAMath::nextMultipleOf<NTHREADS>(80 ); chan += NTHREADS) {
753802 int32_t chanL2Idx = chan / 8 ;
@@ -756,7 +805,6 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBMultiThread(
756805 int32_t chanByteOffset = nBytesBitmask - 1 - CAMath::Popcount (bitmaskL2 >> (chanL2Idx + 1 ));
757806
758807 uint8_t myChannelHasData = (chan < 80 && l2 ? TEST_BIT (PEEK_OVERFLOW (page, chanByteOffset), chan % 8 ) : 0 );
759- assert (myChannelHasData == 0 || myChannelHasData == 1 );
760808
761809 int32_t nSamplesStep;
762810 int32_t threadSampleOffset = CfUtils::warpPredicateScan (myChannelHasData, &nSamplesStep);
@@ -779,13 +827,17 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBMultiThread(
779827
780828 GPUbarrierWarp (); // Ensure all writes to shared memory are finished, before reading it
781829
782- const uint8_t * adcData = ConsumeBytes (page, (nSamplesInTB * DECODE_BITS + 7 ) / 8 );
783- MAYBE_PAGE_OVERFLOW (page); // TODO: We don't need this check?
830+ if (nSamplesInTB > nSamplesLeftInPage) {
831+ return -GPUErrors::ERROR_TPCZS_INVALID_NADC;
832+ }
784833
785834 if (not fragment.contains (timeBin)) {
786835 return FillWithInvalid (clusterer, iThread, NTHREADS, pageDigitOffset, nSamplesInTB);
787836 }
788837
838+ const uint8_t * adcData = ConsumeBytes (page, (nSamplesInTB * DECODE_BITS + 7 ) / 8 );
839+ MAYBE_PAGE_OVERFLOW (page);
840+
789841 // Unpack ADC
790842 int32_t iLink = 0 ;
791843 for (uint16_t sample = iThread; sample < nSamplesInTB; sample += NTHREADS) {
@@ -821,9 +873,6 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBMultiThread(
821873
822874 GPUbarrierWarp (); // Ensure all reads to shared memory are finished, before decoding next header into shmem
823875
824- assert (PayloadExtendsToNextPage || adcData <= page);
825- assert (PayloadExtendsToNextPage || page <= payloadEnd);
826-
827876 return nSamplesInTB;
828877
829878#undef TEST_BIT
@@ -832,13 +881,14 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBMultiThread(
832881}
833882
834883template <bool PayloadExtendsToNextPage>
835- GPUd () uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBSingleThread (
884+ GPUd () int16_t GPUTPCCFDecodeZSDenseLink::DecodeTBSingleThread (
836885 processorType& clusterer,
837886 const uint8_t *& page,
838887 uint32_t pageDigitOffset,
839888 const header::RAWDataHeader* rawDataHeader,
840889 int32_t firstHBF,
841890 int32_t cru,
891+ uint16_t nSamplesLeftInPage,
842892 [[maybe_unused]] const uint8_t * payloadEnd,
843893 [[maybe_unused]] const uint8_t * nextPage)
844894{
@@ -850,7 +900,9 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBSingleThread(
850900 ConsumeBytes (pagePtr, sizeof (header::RAWDataHeader) + diff); \
851901 } \
852902 } else { \
853- assert (pagePtr <= payloadEnd); \
903+ if (pagePtr > payloadEnd) { \
904+ return -GPUErrors::ERROR_TPCZS_PAGE_OVERFLOW; \
905+ } \
854906 }
855907
856908 using zerosupp_link_based::ChannelPerTBHeader;
@@ -898,14 +950,18 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBSingleThread(
898950
899951 } // for (uint8_t iLink = 0; iLink < nLinksInTimebin; iLink++)
900952
901- const uint8_t * adcData = ConsumeBytes (page, (nSamplesInTB * DECODE_BITS + 7 ) / 8 );
902- MAYBE_PAGE_OVERFLOW (page);
953+ if (nSamplesInTB > nSamplesLeftInPage) {
954+ return -GPUErrors::ERROR_TPCZS_INVALID_NADC;
955+ }
903956
904957 if (not fragment.contains (timeBin)) {
905958 FillWithInvalid (clusterer, 0 , 1 , pageDigitOffset, nSamplesInTB);
906959 return nSamplesInTB;
907960 }
908961
962+ const uint8_t * adcData = ConsumeBytes (page, (nSamplesInTB * DECODE_BITS + 7 ) / 8 );
963+ MAYBE_PAGE_OVERFLOW (page);
964+
909965 // Unpack ADC
910966 uint32_t byte = 0 , bits = 0 ;
911967 uint16_t rawFECChannel = 0 ;
@@ -937,10 +993,6 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBSingleThread(
937993 } // while (bits >= DECODE_BITS)
938994 } // while (nSamplesWritten < nAdc)
939995
940- assert (PayloadExtendsToNextPage || adcData <= page);
941- assert (PayloadExtendsToNextPage || page <= payloadEnd);
942- assert (nSamplesWritten == nSamplesInTB);
943-
944996 return nSamplesWritten;
945997
946998#undef MAYBE_PAGE_OVERFLOW
0 commit comments