<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/56289>56289</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            -fsanitize=integer-divide-by-zero can cause functions to fallthrough to subsequent functions
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            question,
            compiler-rt:ubsan
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          nickdesaulniers
      </td>
    </tr>
</table>

<pre>
    Consider the following reduced test case:
```c
struct fb_fix_screeninfo {
  unsigned line_length;
};

struct fb_fix_screeninfo fb_sys_read(int);

long ufx_ops_write_result;
int ufx_ops_write_offset;

void ufx_ops_write(struct fb_fix_screeninfo *info) {
  if (ufx_ops_write_result) {
    int start = ufx_ops_write_offset / info->line_length;
    start = start > 0 ? start : 0;
    int lines = ufx_ops_write_result / info->line_length;
    fb_sys_read(start);
  }
}
void ufx_usb_probe() {}
```
```sh
$ clang -O2 -fsanitize=integer-divide-by-zero -S smscufx.i -o - -fno-asynchronous-unwind-tables -fno-verbose-asm
```
```asm
ufx_ops_write:
        pushq   %rax
        cmpq    $0, ufx_ops_write_result(%rip)
        je      .LBB0_3
        movl    ufx_ops_write_offset(%rip), %eax
        movl    (%rdi), %ecx
        testl   %ecx, %ecx
        je      .LBB0_2
        xorl    %edi, %edi
        xorl    %edx, %edx
        divl    %ecx
        testl   %eax, %eax
        cmovgl  %eax, %edi
        popq    %rax
        jmp     fb_sys_read@PLT
.LBB0_3:
        popq    %rax
        retq
.LBB0_2:
        leaq    .L__unnamed_1(%rip), %rdi
        movq    %rax, %rsi
        xorl    %edx, %edx
        callq   __ubsan_handle_divrem_overflow@PLT
        movq    ufx_ops_write_result(%rip), %rsi
        leaq    .L__unnamed_2(%rip), %rdi
        xorl    %edx, %edx
        callq   __ubsan_handle_divrem_overflow@PLT
.Lfunc_end0:
```
>From what I can tell, it seems that before simplifycfg we have a phi from the overflow handlers with poison values. simplifycfg is turning them into a call to `__ubsan_handle_divrem_overflow` followed by unreachable.
```llvm
; before simplifycfg
define dso_local void @ufx_ops_write(ptr nocapture noundef readonly %info) local_unnamed_addr #0 {
entry:
  %0 = load i64, ptr @ufx_ops_write_result, align 8, !tbaa !5
  %tobool.not = icmp eq i64 %0, 0
  br i1 %tobool.not, label %if.end, label %if.then

if.then:                                          ; preds = %entry
  %1 = load i32, ptr @ufx_ops_write_offset, align 4, !tbaa !9
  %2 = load i32, ptr %info, align 4, !tbaa !11
  %.not = icmp eq i32 %2, 0, !nosanitize !13
  br i1 %.not, label %cont, label %cont.thread, !prof !14, !nosanitize !13

cont.thread:                                      ; preds = %if.then
  %div10 = udiv i32 %1, %2
  %3 = tail call i32 @llvm.smax.i32(i32 %div10, i32 0)
  br label %cont3

cont:                                             ; preds = %if.then
  %4 = zext i32 %1 to i64, !nosanitize !13
  tail call void @__ubsan_handle_divrem_overflow(ptr nonnull @1, i64 %4, i64 0) #4, !nosanitize !13
  %.pr = load i32, ptr %info, align 4, !tbaa !11
  %.not9 = icmp eq i32 %.pr, 0
  br i1 %.not9, label %handler.divrem_overflow2, label %cont3, !prof !14, !nosanitize !13

handler.divrem_overflow2:                         ; preds = %cont
  %5 = load i64, ptr @ufx_ops_write_result, align 8, !tbaa !5
  tail call void @__ubsan_handle_divrem_overflow(ptr nonnull @3, i64 %5, i64 0) #4, !nosanitize !13
  br label %cont3, !nosanitize !13
cont3:                                            ; preds = %cont.thread, %handler.divrem_overflow2, %cont
  %6 = phi i32 [ %3, %cont.thread ], [ poison, %handler.divrem_overflow2 ], [ poison, %cont ]
  %call = tail call i32 @fb_sys_read(i32 noundef %6) #4
  br label %if.end

if.end:                                           ; preds = %cont3, %entry
  ret void
}
```llvm
; after simplifycfg
define dso_local void @ufx_ops_write(ptr nocapture noundef readonly %info) local_unnamed_addr #0 {
entry:
  %0 = load i64, ptr @ufx_ops_write_result, align 8, !tbaa !5
  %tobool.not = icmp eq i64 %0, 0
  br i1 %tobool.not, label %if.end, label %if.then

if.then:                                          ; preds = %entry
  %1 = load i32, ptr @ufx_ops_write_offset, align 4, !tbaa !9
  %2 = load i32, ptr %info, align 4, !tbaa !11
  %.not = icmp eq i32 %2, 0, !nosanitize !13
  br i1 %.not, label %cont, label %cont.thread, !prof !14, !nosanitize !13

cont.thread:                                      ; preds = %if.then
  %div10 = udiv i32 %1, %2
  %3 = tail call i32 @llvm.smax.i32(i32 %div10, i32 0)
  %call = tail call i32 @fb_sys_read(i32 noundef %3) #5
  br label %if.end

cont:                                             ; preds = %if.then
  %4 = zext i32 %1 to i64, !nosanitize !13
  tail call void @__ubsan_handle_divrem_overflow(ptr nonnull @1, i64 %4, i64 0) #5, !nosanitize !13
  %.pr = load i32, ptr %info, align 4, !tbaa !11
  %.not9 = icmp eq i32 %.pr, 0
  call void @llvm.assume(i1 %.not9)
  %5 = load i64, ptr @ufx_ops_write_result, align 8, !tbaa !5
  tail call void @__ubsan_handle_divrem_overflow(ptr nonnull @3, i64 %5, i64 0) #5, !nosanitize !13
  unreachable

if.end:                                           ; preds = %cont.thread, %entry
  ret void
}
```
This comes from [this thread](https://lore.kernel.org/lkml/CAKwvOdnfRnqBF8exO-Y1ooX=67TrO_8fSzgZwvUtidN_P31hzw@mail.gmail.com/) on LKML.  I know we could use `-mllvm -trap-unreachable` here.  Is this a case of "well, the divide by zero case is UB, so we don't need to safely return?"  Because it would be nice if ubsan errors were recoverable.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJztWVtv2zYU_jXOCyFDF18f_JA0CzA0W4utBba9CJREWWwpUiEpO8mv3zmUZEu2cts6YMNaFLZEnvv5eM4JnajsYfNOScMzpoktGMmVEGrP5ZZoltUpy4hlxpKUGjaJLif-9cS_nCz85n_avBur69SSPIlzfh-bVDMmucwVmSyvGgpCatCxlSBOcMliweTWFpOo3Z4sr4_Pz4uEFfNgYs1oNglXXNpJuD7hFQqsr_P7WFUm3mtuGZCbWtgDHbCdEKg8N8yeCNopng3pQOXTzoaX-A329P3mOWysRq0ZEgIpWGUs1ZZMoutR-0DUDUEl3iT6YSyQKOYoonv6gfjweXN4vyT-gAMVozQzorix9VWKh6lxyvrJIQTTfMj3MMK1SeJKqwQj3AXmQN3B7eTVFO1COCOpoJB070NIvNxQyS1_BLxeg2dsy7SX8R0g3EsevEemFfF-JaY0KSiecuLBO3BJ5VHzINNCK6lq49USTkHmWZoICIzb3zGdKMOArnzesgPBEDyH8-Ovq9oUd_A9Ceea3h-W07JqVmf-JHw3DmIM0FzzCmPb8X1h8DG9vbry4-iwWKqdgK9RoPeFgCJ4YT0zWs6WKuM9qvRIhYWhIXPL5wQ9q8LD4r3SHRMKbpjgaWz_IDQ7CoVU9pSO2ULvR1xKwaftOUVPcaWqkYx8KSv47EN75n-8_dTsdxHvJ3ZUimb2rs8S9lkEo3cuUHFcS0lLlsXBSIJ0z1Zwpqel3TevD2JKhUABoDGB4xIXVGaCxRBbzcpYAdBz6AJ9V49KXwTluTkjHoYvePjtPZje5rVMYyYz_7yTNa83WpVkX1BLfoSOJ6H1CYG6ORRmxkoDHRL2EpYrzYjhZSV4_pDmW7JnpKA7RiipCk5yFIPNtDODNNZpQ_bcFqRS3ChJdlTUzEwHgjjoqLXE_gsCSizNCqSitwSewNIXHF74bQuHVps8QNsFzKYFFrHpictC7LoyFl2NONXsZSyHck8yo2KhwAziSjbE9bQvVlYTCRQV2M_gqZbASvDEKCkeMH1dd3RyDkCgWaZhN_KPzZBJqx8OOSLI67vWJBTNCF_MMCeo79SMAxrfESpg3CCrBjmBTSjF73lPpFWJUmIqVdMsOdRewu5QvFOInH5HnmjCgyET7guaMOFcy6eAq9MlyKDszxPdUuTa5ev-YW4qGMWa3oyHwAXn6EbQi0wUPhmZru53kZmdRGbdExmOi-wy-JSIIOjJOI9rFDrZTVwbTqm6Xu34o7NwnwU6VfJ8AaLaDB1OKIwRuRM3e1ZL89lnf21azlIySLXzHk5l0EC2hsfO96CtY2GPMnJUlnLRHHJHOnOHc2pKCgMKZmDVSnByXUWCd_8wAbiIDUJy5uSbQPc6J2du65Hd24ODWKPa8_lMeo_edsXkhaLWVRcpa2ACehfJ9qTOumffDY5h9JJ6xFWlvxHG12MgB_Hj5cNxDPDbdobpicvhGcijvwLvJ6U_g4azzDv4HL2ef-NS_PfREPXQMH8rGs5PznP0DcXbztJoQAc161kUnGdg4QThpOHwNr9yhaRH2wqHrWu3ChTNzPGCuicZUKjbPBrhMjZau07-RIfFbhpA2w9pGYl_20aHLRNX3hTw0Xh34Rm0TxjLHehO_ip9YkSiuWX6-4T0fUL6PiG9NSX_ggnpr5esqC1Z89eVrP_ZtDX_101bA18dTKgxdYkleDCF9aHxHxtqXgp678_-f6SbDqeXN_XU5vVTwQ1JVclMc1sCE4fFpVYujiGrwtrKYJMLb-C_UJpNvzItmZgqvcWVr6WAr3eX7_e7D5nMf5F3Vzcrdv_B-z1Q6jcwd7H8pD_Eq_zXx-0f-91ny7Of449RUDzixVAJKZpu3ScY4pSsiZLk9v1Pt1NCfiRfpdrjzU6qapGR2jC8fvFKRBTxrKaV1w_zwicFAxOBE90AX6j71YS4Whvu26skvBZqbqPxesbdRjsqoP98hQRGoc4MR6-lJZLhLzCKGJozmBEguLWG9gi2hoRcsZSiWdySvbMxgbGCpwx_dHBgI0xrhbdOYBjwpog2dxV0kW2ibB2t6YXlVrDNay7N8UKs0Yf3aJYradCyHEAOWVP1tnCGgmJ2VwMkjmQXtRabYTa33BZ10gbejVnNlwe96QtL4YjdcDi0zMDDfBGu1hfFJqXLIMhn4XKeLRbhPE9oEPjLbJmHi6W_WAcXriibDWAJwgM2GNQOjw1MQ1BWcRh7PY312QUIN-fXF3wT-mHoL8J1sJwFfjAF8WG4DFiWzleLZR4AXJhDiisnAL8LvXHmJvXWYJXhxprjJtQb_LGLOVNAPq1tofQGcvM1Y4bWQnKmzYXzcOPc-xOZlvhi">