createUnsafeSliceStringCheck inserts a runtime check used for unsafe.Slice and unsafe.String. This function must panic if the ptr/len parameters are invalid.
(name string, ptr, len llvm.Value, elementType llvm.Type, lenType *types.Basic)
| 93 | // and unsafe.String. This function must panic if the ptr/len parameters are |
| 94 | // invalid. |
| 95 | func (b *builder) createUnsafeSliceStringCheck(name string, ptr, len llvm.Value, elementType llvm.Type, lenType *types.Basic) { |
| 96 | // From the documentation of unsafe.Slice and unsafe.String: |
| 97 | // > At run time, if len is negative, or if ptr is nil and len is not |
| 98 | // > zero, a run-time panic occurs. |
| 99 | // However, in practice, it is also necessary to check that the length is |
| 100 | // not too big that a GEP wouldn't be possible without wrapping the pointer. |
| 101 | // These two checks (non-negative and not too big) can be merged into one |
| 102 | // using an unsigned greater than. |
| 103 | |
| 104 | // Make sure the len value is at least as big as a uintptr. |
| 105 | len = b.extendInteger(len, lenType, b.uintptrType) |
| 106 | |
| 107 | // Determine the maximum slice size, and therefore the maximum value of the |
| 108 | // len parameter. |
| 109 | maxSize := b.maxSliceSize(elementType) |
| 110 | maxSizeValue := llvm.ConstInt(len.Type(), maxSize, false) |
| 111 | |
| 112 | // Do the check. By using unsigned greater than for the length check, signed |
| 113 | // negative values are also checked (which are very large numbers when |
| 114 | // interpreted as signed values). |
| 115 | zero := llvm.ConstInt(len.Type(), 0, false) |
| 116 | lenOutOfBounds := b.CreateICmp(llvm.IntUGT, len, maxSizeValue, "") |
| 117 | ptrIsNil := b.CreateICmp(llvm.IntEQ, ptr, llvm.ConstNull(ptr.Type()), "") |
| 118 | lenIsNotZero := b.CreateICmp(llvm.IntNE, len, zero, "") |
| 119 | assert := b.CreateAnd(ptrIsNil, lenIsNotZero, "") |
| 120 | assert = b.CreateOr(assert, lenOutOfBounds, "") |
| 121 | b.createRuntimeAssert(assert, name, "unsafeSlicePanic") |
| 122 | } |
| 123 | |
| 124 | // createChanBoundsCheck creates a bounds check before creating a new channel to |
| 125 | // check that the value is not too big for runtime.chanMake. |
no test coverage detected