From 67e38c4cf652927fd3b1e99897a4da0c3c0fe804 Mon Sep 17 00:00:00 2001 From: linlin-s Date: Tue, 7 Nov 2023 15:09:10 -0800 Subject: [PATCH 1/3] Implements patch list as a single contiguous array of reusable PatchPoint instances. (#521) --- .../ion/impl/_Private_RecyclingQueue.java | 122 +++++++ .../ion/impl/_Private_RecyclingStack.java | 87 ++++- .../ion/impl/bin/IonRawBinaryWriter.java | 300 +++++------------- 3 files changed, 292 insertions(+), 217 deletions(-) create mode 100644 src/com/amazon/ion/impl/_Private_RecyclingQueue.java diff --git a/src/com/amazon/ion/impl/_Private_RecyclingQueue.java b/src/com/amazon/ion/impl/_Private_RecyclingQueue.java new file mode 100644 index 0000000000..a52ccd7a35 --- /dev/null +++ b/src/com/amazon/ion/impl/_Private_RecyclingQueue.java @@ -0,0 +1,122 @@ +package com.amazon.ion.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +/** + * A queue whose elements are recycled. This queue will be extended and iterated frequently. + * @param the type of elements stored. + */ +public class _Private_RecyclingQueue { + + /** + * Factory for new queue elements. + * @param the type of element. + */ + public interface ElementFactory { + /** + * @return a new instance. + */ + T newElement(); + } + + @FunctionalInterface + public interface Recycler { + /** + * Re-initialize an element + */ + void recycle(T t); + } + + /** + * Iterator for the queue. + */ + private class ElementIterator implements Iterator { + int i = 0; + @Override + public boolean hasNext() { + return i <= currentIndex; + } + + @Override + public T next() { + return elements.get(i++); + } + } + + private final ElementIterator iterator; + private final List elements; + private final ElementFactory elementFactory; + private int currentIndex; + private T top; + + /** + * @param initialCapacity the initial capacity of the underlying collection. + * @param elementFactory the factory used to create a new element on {@link #push()} when the queue has + * not previously grown to the new depth. + */ + public _Private_RecyclingQueue(int initialCapacity, ElementFactory elementFactory) { + elements = new ArrayList(initialCapacity); + this.elementFactory = elementFactory; + currentIndex = -1; + iterator = new ElementIterator(); + } + + public void truncate(int index) { + currentIndex = index; + } + + public T get(int index) { + return elements.get(index); + } + + /** + * Pushes an element onto the top of the queue, instantiating a new element only if the queue has not + * previously grown to the new depth. + * @return the element at the top of the queue after the push. This element must be initialized by the caller. + */ + public int push(Recycler recycler) { + currentIndex++; + if (currentIndex >= elements.size()) { + top = elementFactory.newElement(); + elements.add(top); + } else { + top = elements.get(currentIndex); + } + recycler.recycle(top); + return currentIndex; + } + + /** + * Reclaim the current element. + */ + public void remove() { + currentIndex = Math.max(-1, currentIndex - 1); + } + + public Iterator iterate() { + iterator.i = 0; + return iterator; + } + + /** + * @return true if the queue is empty; otherwise, false. + */ + public boolean isEmpty() { + return currentIndex < 0; + } + + /** + * Reset the index and make the queue reusable. + */ + public void clear() { + currentIndex = -1; + } + + /** + * @return the number of elements within the queue. + */ + public int size() { + return currentIndex + 1; + } +} \ No newline at end of file diff --git a/src/com/amazon/ion/impl/_Private_RecyclingStack.java b/src/com/amazon/ion/impl/_Private_RecyclingStack.java index a98e09d410..d88ac040ff 100644 --- a/src/com/amazon/ion/impl/_Private_RecyclingStack.java +++ b/src/com/amazon/ion/impl/_Private_RecyclingStack.java @@ -2,13 +2,25 @@ import java.util.ArrayList; import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; /** * A stack whose elements are recycled. This can be useful when the stack needs to grow and shrink * frequently and has a predictable maximum depth. * @param the type of elements stored. */ -public final class _Private_RecyclingStack { +public final class _Private_RecyclingStack implements Iterable { + public $Iterator stackIterator; + @Override + public ListIterator iterator() { + if (stackIterator != null) { + stackIterator.cursor = _Private_RecyclingStack.this.currentIndex; + } else { + stackIterator = new $Iterator(); + } + return stackIterator; + } /** * Factory for new stack elements. @@ -22,6 +34,14 @@ public interface ElementFactory { T newElement(); } + @FunctionalInterface + public interface Recycler { + /** + * Re-initialize an element + */ + void recycle(T t); + } + private final List elements; private final ElementFactory elementFactory; private int currentIndex; @@ -29,11 +49,11 @@ public interface ElementFactory { /** * @param initialCapacity the initial capacity of the underlying collection. - * @param elementFactory the factory used to create a new element on {@link #push()} when the stack has + * @param elementFactory the factory used to create a new element on {@link #push(Recycler)} when the stack has * not previously grown to the new depth. */ public _Private_RecyclingStack(int initialCapacity, ElementFactory elementFactory) { - elements = new ArrayList(initialCapacity); + elements = new ArrayList<>(initialCapacity); this.elementFactory = elementFactory; currentIndex = -1; top = null; @@ -44,7 +64,7 @@ public _Private_RecyclingStack(int initialCapacity, ElementFactory elementFac * previously grown to the new depth. * @return the element at the top of the stack after the push. This element must be initialized by the caller. */ - public T push() { + public T push(Recycler recycler) { currentIndex++; if (currentIndex >= elements.size()) { top = elementFactory.newElement(); @@ -52,6 +72,7 @@ public T push() { } else { top = elements.get(currentIndex); } + recycler.recycle(top); return top; } @@ -92,4 +113,62 @@ public boolean isEmpty() { public int size() { return currentIndex + 1; } + + private class $Iterator implements ListIterator { + private int cursor; + + @Override + public boolean hasNext() { + return cursor >= 0; + } + + @Override + public T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + // post-decrement because "next" is where the cursor is + return _Private_RecyclingStack.this.elements.get(cursor--); + } + + @Override + public boolean hasPrevious() { + return cursor + 1 <= _Private_RecyclingStack.this.currentIndex; + } + + @Override + public T previous() { + if (!hasPrevious()) { + throw new NoSuchElementException(); + } + // pre-increment: "next" is where the cursor is, so "previous" is upward in stack + return _Private_RecyclingStack.this.elements.get(++cursor); + } + + @Override + public int nextIndex() { + return cursor; + } + + @Override + public int previousIndex() { + return cursor + 1; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + @Override + public void set(T t) { + throw new UnsupportedOperationException(); + } + + @Override + public void add(T t) { + throw new UnsupportedOperationException(); + } + } + } diff --git a/src/com/amazon/ion/impl/bin/IonRawBinaryWriter.java b/src/com/amazon/ion/impl/bin/IonRawBinaryWriter.java index e5bda78333..ab493ab5d4 100644 --- a/src/com/amazon/ion/impl/bin/IonRawBinaryWriter.java +++ b/src/com/amazon/ion/impl/bin/IonRawBinaryWriter.java @@ -46,6 +46,7 @@ import com.amazon.ion.SymbolTable; import com.amazon.ion.SymbolToken; import com.amazon.ion.Timestamp; +import com.amazon.ion.impl._Private_RecyclingQueue; import com.amazon.ion.impl._Private_RecyclingStack; import com.amazon.ion.impl.bin.utf8.Utf8StringEncoder; import com.amazon.ion.impl.bin.utf8.Utf8StringEncoderPool; @@ -54,10 +55,8 @@ import java.io.OutputStream; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.ArrayList; import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; +import java.util.ListIterator; /** * Low-level binary {@link IonWriter} that understands encoding concerns but doesn't operate with any sense of symbol table management. @@ -248,74 +247,67 @@ private ContainerType(final boolean allowedInStepOut) } } - private static class ContainerInfo + private class ContainerInfo { - /** Whether or not the container is a struct */ + /** Whether the container is a struct */ public ContainerType type; /** The location of the pre-allocated size descriptor in the buffer. */ public long position; /** The size of the current value. */ public long length; - /** The patchlist for this container. */ - public PatchList patches; + /** + * The index of the patch point if present, -1 otherwise. + */ + public int patchIndex; public ContainerInfo() { type = null; position = -1; length = -1; - patches = null; + patchIndex = -1; } - public void appendPatch(final PatchPoint patch) + public void appendPatch(final long oldPosition, final int oldLength, final long length) { - if (patches == null) - { - patches = new PatchList(); + if (patchIndex == -1) { + // We have no assigned patch point, we need to make our own + patchIndex = patchPoints.push(p -> p.initialize(oldPosition, oldLength, length)); + } else { + // We have an assigned patch point already, but we need to overwrite it with the correct data + patchPoints.get(patchIndex).initialize(oldPosition, oldLength, length); } - patches.append(patch); } - public void extendPatches(final PatchList newPatches) - { - if (patches == null) - { - patches = newPatches; - } - else - { - patches.extend(newPatches); - } - } - - public void initialize(final ContainerType type, final long offset) { + public ContainerInfo initialize(final ContainerType type, final long offset) { this.type = type; this.position = offset; - this.patches = null; this.length = 0; + this.patchIndex = -1; + + return this; } @Override public String toString() { - return "(CI " + type + " pos:" + position + " len:" + length + ")"; + return "(CI " + type + " pos:" + position + " len:" + length + " patch:"+patchIndex+")"; } } private static class PatchPoint { /** position of the data being patched out. */ - public final long oldPosition; + public long oldPosition; /** length of the data being patched out.*/ - public final int oldLength; + public int oldLength; /** size of the container data or annotations.*/ - public final long length; - - public PatchPoint(final long oldPosition, final int oldLength, final long patchLength) + public long length; + public PatchPoint() { - this.oldPosition = oldPosition; - this.oldLength = oldLength; - this.length = patchLength; + oldPosition = -1; + oldLength = -1; + length = -1; } @Override @@ -323,146 +315,16 @@ public String toString() { return "(PP old::(" + oldPosition + " " + oldLength + ") patch::(" + length + ")"; } - } - - /** - * Simple singly linked list node that we can use to construct the patch list in the - * right order incrementally in recursive segments. - */ - private static class PatchList implements Iterable - { - private static class Node { - public final PatchPoint value; - public Node next; - - public Node(final PatchPoint value) - { - this.value = value; - } - } - private Node head; - private Node tail; - - public PatchList() - { - head = null; - tail = null; - } - - public boolean isEmpty() - { - return head == null && tail == null; - } - - public void clear() - { - head = null; - tail = null; - } - - public void append(final PatchPoint patch) - { - final Node node = new Node(patch); - if (head == null) - { - head = node; - tail = node; - } - else - { - tail.next = node; - tail = node; - } - } - - public void extend(final PatchList end) - { - if (end != null) - { - if (head == null) - { - if (end.head != null) - { - head = end.head; - tail = end.tail; - } - } - else - { - tail.next = end.head; - tail = end.tail; - } - } - } - - public PatchPoint truncate(final long oldPosition) - { - Node prev = null; - Node curr = head; - while (curr != null) - { - final PatchPoint patch = curr.value; - if (patch.oldPosition >= oldPosition) - { - tail = prev; - if (tail == null) - { - head = null; - } - else - { - tail.next = null; - } - return patch; - } - - prev = curr; - curr = curr.next; - } - return null; - } - - public Iterator iterator() - { - return new Iterator() - { - Node curr = head; - - public boolean hasNext() - { - return curr != null; - } - public PatchPoint next() - { - if (!hasNext()) - { - throw new NoSuchElementException(); - } - final PatchPoint value = curr.value; - curr = curr.next; - return value; - } - - public void remove() - { - throw new UnsupportedOperationException(); - } - }; + public PatchPoint initialize(final long oldPosition, final int oldLength, final long length) { + this.oldPosition = oldPosition; + this.oldLength = oldLength; + this.length = length; + return this; } - @Override - public String toString() - { - final StringBuilder buf = new StringBuilder(); - buf.append("(PATCHES"); - for (final PatchPoint patch : this) - { - buf.append(" "); - buf.append(patch); - } - buf.append(")"); - return buf.toString(); + public PatchPoint clear() { + return initialize(-1, -1, -1); } } @@ -487,7 +349,7 @@ public String toString() private final PreallocationMode preallocationMode; private final boolean isFloatBinary32Enabled; private final WriteBuffer buffer; - private final PatchList patchPoints; + private final _Private_RecyclingQueue patchPoints; private final _Private_RecyclingStack containers; private int depth; private boolean hasWrittenValuesSinceFinished; @@ -521,7 +383,7 @@ public String toString() this.preallocationMode = preallocationMode; this.isFloatBinary32Enabled = isFloatBinary32Enabled; this.buffer = new WriteBuffer(allocator); - this.patchPoints = new PatchList(); + this.patchPoints = new _Private_RecyclingQueue<>(512, PatchPoint::new); this.containers = new _Private_RecyclingStack( 10, new _Private_RecyclingStack.ElementFactory() { @@ -537,7 +399,6 @@ public ContainerInfo newElement() { this.currentFieldSid = SID_UNASSIGNED; this.currentAnnotationSids = new IntList(); this.hasTopLevelSymbolTableAnnotation = false; - this.closed = false; } @@ -690,38 +551,40 @@ private void updateLength(long length) private void pushContainer(final ContainerType type) { // XXX we push before writing the type of container - containers.push().initialize(type, buffer.position() + 1); + containers.push(c -> c.initialize(type, buffer.position() + 1)); } - private void addPatchPoint(final long position, final int oldLength, final long value) + private void addPatchPoint(final ContainerInfo container, final long position, final int oldLength, final long value) { - // record the length of the patch - final int patchLength = WriteBuffer.varUIntLength(value); - final PatchPoint patch = new PatchPoint(position, oldLength, value); - if (containers.isEmpty()) - { - // not nested, just append to the root list - patchPoints.append(patch); - } - else - { - // nested, apply it to the current container - containers.peek().appendPatch(patch); + // If we're adding a patch point we first need to ensure that all of our ancestors (containing values) already + // have a patch point. No container can be smaller than the contents, so all outer layers also require patches. + // Instead of allocating iterator, we share one iterator instance within the scope of the container stack and reset the cursor every time we track back to the ancestors. + ListIterator stackIterator = containers.iterator(); + // Walk down the stack until we find an ancestor which already has a patch point + while (stackIterator.hasNext() && stackIterator.next().patchIndex == -1); + + // The iterator cursor is now positioned on an ancestor container that has a patch point + // Ascend back up the stack, fixing the ancestors which need a patch point assigned before us + while (stackIterator.hasPrevious()) { + ContainerInfo ancestor = stackIterator.previous(); + if (ancestor.patchIndex == -1) { + ancestor.patchIndex = patchPoints.push(PatchPoint::clear); + } } + + // record the size of the length data. + final int patchLength = WriteBuffer.varUIntLength(value); + container.appendPatch(position, oldLength, value); updateLength(patchLength - oldLength); } - private void extendPatchPoints(final PatchList patches) - { - if (containers.isEmpty()) - { - // not nested, extend root list - patchPoints.extend(patches); - } - else - { - // nested, apply it to the current container - containers.peek().extendPatches(patches); + /** + * This is used to reclaim the placeholder patch point after scan the current container. + * @param placeholderPatchIndex represents the index of the placeholder patch point. + */ + private void reclaimPlaceholderPatchPoint(int placeholderPatchIndex) { + if (placeholderPatchIndex >= patchPoints.size() - 1) { + patchPoints.remove(); } } @@ -776,17 +639,11 @@ else if (currentContainer.length <= preallocationMode.contentMaxLength) else { // The container's encoded body is too long to fit in the length bytes that were preallocated. - // Write the VarUInt encoding of the length in a secondary buffer and make a note to include that - // when we go to flush the primary buffer to the output stream. - addPatchPoint(positionOfFirstLengthByte, preallocationMode.numberOfLengthBytes(), length); + // Write the length in the patch point list, making a note to include the VarUInt encoding of the length + // at the right point when we go to flush the primary buffer to the output stream. + addPatchPoint(currentContainer, positionOfFirstLengthByte, preallocationMode.numberOfLengthBytes(), length); } } - if (currentContainer.patches != null) - { - // at this point, we've appended our patch points upward, lets make sure we get - // our child patch points in - extendPatchPoints(currentContainer.patches); - } // make sure to record length upward updateLength(length); @@ -1230,7 +1087,7 @@ private void patchSingleByteTypedOptimisticValue(final byte type, final Containe { // side patch buffer.writeUInt8At(info.position - 1, type | 0xE); - addPatchPoint(info.position, 0, info.length); + addPatchPoint(info, info.position, 0, info.length); } } @@ -1484,7 +1341,19 @@ public void writeBytes(byte[] data, int offset, int length) throws IOException /*package*/ void truncate(long position) { buffer.truncate(position); - patchPoints.truncate(position); + // TODO decide if it is worth making this faster than O(N) + Iterator patchIterator = patchPoints.iterate(); + int i = 0; + while (patchIterator.hasNext()) { + PatchPoint patchPoint = patchIterator.next(); + if (patchPoint.length > -1) { + if (patchPoint.oldPosition >= position) { + patchPoints.truncate(i - 1); + break; + } + } + i++; + } } public void flush() throws IOException {} @@ -1508,8 +1377,13 @@ public void finish() throws IOException else { long bufferPosition = 0; - for (final PatchPoint patch : patchPoints) + Iterator iterator = patchPoints.iterate(); + while (iterator.hasNext()) { + PatchPoint patch = iterator.next(); + if (patch.length < 0) { + continue; + } // write up to the thing to be patched final long bufferLength = patch.oldPosition - bufferPosition; buffer.writeTo(out, bufferPosition, bufferLength); From 2f48f49deadd1d4a3f21614df5f1cb5ee1792dde Mon Sep 17 00:00:00 2001 From: linlin-s Date: Tue, 7 Nov 2023 15:30:01 -0800 Subject: [PATCH 2/3] Remove the repeated logic of the method that overwrites the lower nibble of container type descriptor. (#548) --- .../ion/impl/bin/IonRawBinaryWriter.java | 14 ++++------- src/com/amazon/ion/impl/bin/WriteBuffer.java | 25 ++++++++++--------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/com/amazon/ion/impl/bin/IonRawBinaryWriter.java b/src/com/amazon/ion/impl/bin/IonRawBinaryWriter.java index ab493ab5d4..216b139e33 100644 --- a/src/com/amazon/ion/impl/bin/IonRawBinaryWriter.java +++ b/src/com/amazon/ion/impl/bin/IonRawBinaryWriter.java @@ -610,22 +610,18 @@ private ContainerInfo popContainer() // The number of bytes we need to shift by is determined by the writer's preallocation mode. final int numberOfBytesToShiftBy = preallocationMode.numberOfLengthBytes(); - // `length` is the encoded length of the container/wrapper we're stepping out of. It does not - // include any header bytes. In this `if` branch, we've confirmed that `length` is <= 0xD, - // so this downcast from `long` to `int` is safe. - final int lengthOfSliceToShift = (int) length; - // Shift the container/wrapper body backwards in the buffer. Because this only happens when // `lengthOfSliceToShift` is 13 or fewer bytes, this will usually be a very fast memcpy. // It's slightly more work if the slice we're shifting happens to straddle two memory blocks // inside the buffer. - buffer.shiftBytesLeft(lengthOfSliceToShift, numberOfBytesToShiftBy); + // `length` is the encoded length of the container/wrapper we're stepping out of. It does not + // include any header bytes. In this `if` branch, we've confirmed that `length` is <= 0xD, + // so this downcast from `long` to `int` is safe. + buffer.shiftBytesLeft((int)length, numberOfBytesToShiftBy); // Overwrite the lower nibble of the original type descriptor byte with the body's encoded length. final long typeDescriptorPosition = positionOfFirstLengthByte - 1; - final long type = (buffer.getUInt8At(typeDescriptorPosition) & 0xF0) | length; - buffer.writeUInt8At(typeDescriptorPosition, type); - + buffer.writeLowerNibbleAt(typeDescriptorPosition, length); // We've reclaimed some number of bytes; adjust the container length as appropriate. length -= numberOfBytesToShiftBy; } diff --git a/src/com/amazon/ion/impl/bin/WriteBuffer.java b/src/com/amazon/ion/impl/bin/WriteBuffer.java index fba4c60d48..7e67af00bd 100644 --- a/src/com/amazon/ion/impl/bin/WriteBuffer.java +++ b/src/com/amazon/ion/impl/bin/WriteBuffer.java @@ -104,17 +104,6 @@ public long position() return (((long) index) * allocator.getBlockSize()) + current.limit; } - private static final int OCTET_MASK = 0xFF; - - /** Returns the octet at the logical position given. */ - public int getUInt8At(final long position) - { - final int index = index(position); - final int offset = offset(position); - final Block block = blocks.get(index); - return block.data[offset] & OCTET_MASK; - } - /** Writes a single octet to the buffer, expanding if necessary. */ public void writeByte(final byte octet) { @@ -1266,12 +1255,24 @@ public void writeUInt8At(final long position, final long value) { final int index = index(position); final int offset = offset(position); - // XXX we'll never overrun a block unless we're given a position past our block array final Block block = blocks.get(index); block.data[offset] = (byte) value; } + /** + * Overwrite the lower nibble of the specified type descriptor byte with the length information. + * @param position represents the position of the byte that will be overwritten. + * @param value represents the length value of the container. + */ + public void writeLowerNibbleAt(final long position, final long value) { + final int index = index(position); + final int offset = offset(position); + final Block block = blocks.get(index); + long bitValue = block.data[offset]; + block.data[offset] = (byte) (bitValue & 0xF0 | value) ; + } + /** Get the length of FlexInt for the provided value. */ public static int flexIntLength(final long value) { int numMagnitudeBitsRequired; From 0d0258cc546dab0277cbd4be09e0c0f52e724e4f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Nov 2023 09:34:54 -0800 Subject: [PATCH 3/3] Bump github/codeql-action from 2.22.5 to 2.22.6 (#638) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.5 to 2.22.6. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/74483a38d39275f33fcff5f35b679b5ca4a26a99...689fdc5193eeb735ecb2e52e819e3382876f93f4) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecard.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 3cfc22f09c..ad6258db61 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -41,7 +41,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5 + uses: github/codeql-action/init@689fdc5193eeb735ecb2e52e819e3382876f93f4 # v2.22.6 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -52,7 +52,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5 + uses: github/codeql-action/autobuild@689fdc5193eeb735ecb2e52e819e3382876f93f4 # v2.22.6 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -66,4 +66,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5 + uses: github/codeql-action/analyze@689fdc5193eeb735ecb2e52e819e3382876f93f4 # v2.22.6 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index a894ddce1c..a9832c88c7 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5 + uses: github/codeql-action/upload-sarif@689fdc5193eeb735ecb2e52e819e3382876f93f4 # v2.22.6 with: sarif_file: results.sarif