sijms / go-ora

Pure go oracle client
MIT License
767 stars 168 forks source link

"panic: runtime error: slice bounds out of range" when output array size is bigger than 245 #554

Closed rfoh closed 2 months ago

rfoh commented 2 months ago

I'm using version 2.8.16 and trying to use udt array. When the udt array has more than 245 elements, I get a panic error. I created a simple test case that replicates this issue.

package main

import (
    "database/sql"
    "flag"
    "fmt"
    "os"
    "time"

    go_ora "github.com/sijms/go-ora/v2"
)

func execCmd(db *sql.DB, stmts ...string) error {
    for _, stmt := range stmts {
        if _, err := db.Exec(stmt); err != nil {
            if len(stmts) > 1 {
                return fmt.Errorf("error: %v in execuation of stmt: %s", err, stmt)
            } else {
                return err
            }
        }
    }
    return nil
}

func createTypes(db *sql.DB) error {
    return execCmd(db, `
        create or replace type stringsType as object(
            STRING1 varchar2(60),
            STRING2 varchar2(300)
        )`,
        `create or replace type stringsTypeCol as table of stringsType`)
}

func dropTypes(db *sql.DB) error {
    return execCmd(db,
        "DROP TYPE stringsTypeCol",
        "DROP TYPE stringsType")
}

type StringsType struct {
    String1 string `udt:"STRING1"`
    String2 string `udt:"STRING2"`
}

func execSql(db *sql.DB, len int) {
    start := time.Now()

    var output []StringsType
    _, err := db.Exec(`
    declare
        outp stringsTypeCol;
        ext number;
    begin 
        ext := :1;
        outp := stringsTypeCol();
        outp.extend(ext);
        for n in 1..ext
        loop
            outp(n) := stringsType('string1','string2');
        end loop;

        :2 := outp;
    end;
    `, len, go_ora.Out{Dest: &output})
    if err != nil {
        fmt.Println("can't execute query:", err)
        return
    }
    elapsed := time.Since(start)
    fmt.Println("length: ", len, " - sql exec took: ", elapsed)
}

func main() {
    db, err := sql.Open("oracle", os.Getenv("DSN"))
    if err != nil {
        fmt.Println(err.Error())
    }
    defer db.Close()

    err = createTypes(db)
    if err != nil {
        fmt.Println("can't create types: ", err)
        return
    }
    defer func() {
        err = dropTypes(db)
        if err != nil {
            fmt.Println("can't drop types: ", err)
        }
    }()

    err = go_ora.RegisterType(db, "stringsType", "stringsTypeCol", StringsType{})
    if err != nil {
        fmt.Println("can't register stringsType: ", err)
        return
    }

    var nFlag int
    flag.IntVar(&nFlag, "n", 246, "udt array length") // if n > 245 then panic error! 
    flag.Parse()
    for i := 1; i <= nFlag; i++ {
        execSql(db, i)
    }

}
length:  1  - sql exec took:  4.427908ms
length:  2  - sql exec took:  497.154µs
length:  3  - sql exec took:  327.654µs
length:  4  - sql exec took:  298.641µs
length:  5  - sql exec took:  305.749µs
length:  6  - sql exec took:  344.414µs
length:  7  - sql exec took:  401.029µs
length:  8  - sql exec took:  333.747µs
length:  9  - sql exec took:  203.013µs
length:  10  - sql exec took:  235.049µs
length:  11  - sql exec took:  206.798µs
length:  12  - sql exec took:  190.101µs
length:  13  - sql exec took:  213.209µs
length:  14  - sql exec took:  228.06µs
length:  15  - sql exec took:  207.755µs
length:  16  - sql exec took:  204.471µs
length:  17  - sql exec took:  224.67µs
length:  18  - sql exec took:  218.414µs
length:  19  - sql exec took:  215.659µs
length:  20  - sql exec took:  236.109µs
length:  21  - sql exec took:  238.372µs
length:  22  - sql exec took:  745.486µs
length:  23  - sql exec took:  311.011µs
length:  24  - sql exec took:  261.131µs
length:  25  - sql exec took:  245.266µs
length:  26  - sql exec took:  264.245µs
length:  27  - sql exec took:  279.723µs
length:  28  - sql exec took:  265.567µs
length:  29  - sql exec took:  260.044µs
length:  30  - sql exec took:  269.383µs
length:  31  - sql exec took:  246.777µs
length:  32  - sql exec took:  258.494µs
length:  33  - sql exec took:  261.535µs
length:  34  - sql exec took:  253.357µs
length:  35  - sql exec took:  249.226µs
length:  36  - sql exec took:  260.421µs
length:  37  - sql exec took:  551.534µs
length:  38  - sql exec took:  395.816µs
length:  39  - sql exec took:  292.3µs
length:  40  - sql exec took:  273.434µs
length:  41  - sql exec took:  272.199µs
length:  42  - sql exec took:  270.356µs
length:  43  - sql exec took:  275.59µs
length:  44  - sql exec took:  271.922µs
length:  45  - sql exec took:  285.255µs
length:  46  - sql exec took:  290.326µs
length:  47  - sql exec took:  298.476µs
length:  48  - sql exec took:  585.874µs
length:  49  - sql exec took:  381.778µs
length:  50  - sql exec took:  354.161µs
length:  51  - sql exec took:  342.508µs
length:  52  - sql exec took:  327.563µs
length:  53  - sql exec took:  320.362µs
length:  54  - sql exec took:  330.187µs
length:  55  - sql exec took:  345.392µs
length:  56  - sql exec took:  328.536µs
length:  57  - sql exec took:  539.831µs
length:  58  - sql exec took:  399.588µs
length:  59  - sql exec took:  348.986µs
length:  60  - sql exec took:  347.651µs
length:  61  - sql exec took:  356.859µs
length:  62  - sql exec took:  371.924µs
length:  63  - sql exec took:  374.73µs
length:  64  - sql exec took:  380.08µs
length:  65  - sql exec took:  581.247µs
length:  66  - sql exec took:  498.174µs
length:  67  - sql exec took:  399.041µs
length:  68  - sql exec took:  400.713µs
length:  69  - sql exec took:  406.119µs
length:  70  - sql exec took:  403.393µs
length:  71  - sql exec took:  396.674µs
length:  72  - sql exec took:  393.794µs
length:  73  - sql exec took:  566.408µs
length:  74  - sql exec took:  434.753µs
length:  75  - sql exec took:  408.463µs
length:  76  - sql exec took:  385.863µs
length:  77  - sql exec took:  424.013µs
length:  78  - sql exec took:  432.306µs
length:  79  - sql exec took:  731.631µs
length:  80  - sql exec took:  516.922µs
length:  81  - sql exec took:  697.77µs
length:  82  - sql exec took:  555.56µs
length:  83  - sql exec took:  524.561µs
length:  84  - sql exec took:  452.508µs
length:  85  - sql exec took:  689.885µs
length:  86  - sql exec took:  555.027µs
length:  87  - sql exec took:  447.989µs
length:  88  - sql exec took:  447.621µs
length:  89  - sql exec took:  435.871µs
length:  90  - sql exec took:  511.935µs
length:  91  - sql exec took:  671.612µs
length:  92  - sql exec took:  559.861µs
length:  93  - sql exec took:  450.908µs
length:  94  - sql exec took:  472.231µs
length:  95  - sql exec took:  605.442µs
length:  96  - sql exec took:  734.18µs
length:  97  - sql exec took:  507.165µs
length:  98  - sql exec took:  483.421µs
length:  99  - sql exec took:  465.493µs
length:  100  - sql exec took:  486.794µs
length:  101  - sql exec took:  811.518µs
length:  102  - sql exec took:  502.764µs
length:  103  - sql exec took:  530.427µs
length:  104  - sql exec took:  486.593µs
length:  105  - sql exec took:  760.812µs
length:  106  - sql exec took:  512.109µs
length:  107  - sql exec took:  532.145µs
length:  108  - sql exec took:  518.384µs
length:  109  - sql exec took:  791.317µs
length:  110  - sql exec took:  556.681µs
length:  111  - sql exec took:  511.381µs
length:  112  - sql exec took:  587.442µs
length:  113  - sql exec took:  713.064µs
length:  114  - sql exec took:  595.123µs
length:  115  - sql exec took:  558.073µs
length:  116  - sql exec took:  546.004µs
length:  117  - sql exec took:  763.693µs
length:  118  - sql exec took:  566.066µs
length:  119  - sql exec took:  581.78µs
length:  120  - sql exec took:  746.205µs
length:  121  - sql exec took:  592.006µs
length:  122  - sql exec took:  549.766µs
length:  123  - sql exec took:  892.226µs
length:  124  - sql exec took:  612.197µs
length:  125  - sql exec took:  637.199µs
length:  126  - sql exec took:  700.923µs
length:  127  - sql exec took:  796.568µs
length:  128  - sql exec took:  650.118µs
length:  129  - sql exec took:  594.13µs
length:  130  - sql exec took:  1.011568ms
length:  131  - sql exec took:  754.178µs
length:  132  - sql exec took:  743.682µs
length:  133  - sql exec took:  927.103µs
length:  134  - sql exec took:  658.289µs
length:  135  - sql exec took:  614.758µs
length:  136  - sql exec took:  617.712µs
length:  137  - sql exec took:  836.627µs
length:  138  - sql exec took:  653.322µs
length:  139  - sql exec took:  600.171µs
length:  140  - sql exec took:  619.56µs
length:  141  - sql exec took:  838.507µs
length:  142  - sql exec took:  689.329µs
length:  143  - sql exec took:  651.913µs
length:  144  - sql exec took:  785.535µs
length:  145  - sql exec took:  679.166µs
length:  146  - sql exec took:  644.923µs
length:  147  - sql exec took:  920.894µs
length:  148  - sql exec took:  758.445µs
length:  149  - sql exec took:  712.211µs
length:  150  - sql exec took:  921.833µs
length:  151  - sql exec took:  756.804µs
length:  152  - sql exec took:  770.456µs
length:  153  - sql exec took:  956.264µs
length:  154  - sql exec took:  685.255µs
length:  155  - sql exec took:  659.372µs
length:  156  - sql exec took:  941.749µs
length:  157  - sql exec took:  754.902µs
length:  158  - sql exec took:  730.7µs
length:  159  - sql exec took:  1.030333ms
length:  160  - sql exec took:  768.936µs
length:  161  - sql exec took:  924.133µs
length:  162  - sql exec took:  921.451µs
length:  163  - sql exec took:  706.485µs
length:  164  - sql exec took:  688.671µs
length:  165  - sql exec took:  919.452µs
length:  166  - sql exec took:  758.014µs
length:  167  - sql exec took:  877.372µs
length:  168  - sql exec took:  929.068µs
length:  169  - sql exec took:  731.922µs
length:  170  - sql exec took:  795.038µs
length:  171  - sql exec took:  1.077097ms
length:  172  - sql exec took:  872.054µs
length:  173  - sql exec took:  743.594µs
length:  174  - sql exec took:  1.122643ms
length:  175  - sql exec took:  963.732µs
length:  176  - sql exec took:  986.301µs
length:  177  - sql exec took:  815.939µs
length:  178  - sql exec took:  1.040157ms
length:  179  - sql exec took:  805.343µs
length:  180  - sql exec took:  981.297µs
length:  181  - sql exec took:  791.948µs
length:  182  - sql exec took:  908.007µs
length:  183  - sql exec took:  826.126µs
length:  184  - sql exec took:  998.046µs
length:  185  - sql exec took:  968.862µs
length:  186  - sql exec took:  1.01725ms
length:  187  - sql exec took:  808.851µs
length:  188  - sql exec took:  1.085912ms
length:  189  - sql exec took:  931.917µs
length:  190  - sql exec took:  1.075405ms
length:  191  - sql exec took:  834.499µs
length:  192  - sql exec took:  1.171666ms
length:  193  - sql exec took:  906.746µs
length:  194  - sql exec took:  1.086089ms
length:  195  - sql exec took:  974.506µs
length:  196  - sql exec took:  1.106615ms
length:  197  - sql exec took:  894.95µs
length:  198  - sql exec took:  1.127567ms
length:  199  - sql exec took:  916.518µs
length:  200  - sql exec took:  1.155594ms
length:  201  - sql exec took:  1.037028ms
length:  202  - sql exec took:  1.162247ms
length:  203  - sql exec took:  999.491µs
length:  204  - sql exec took:  1.103755ms
length:  205  - sql exec took:  910.372µs
length:  206  - sql exec took:  1.137736ms
length:  207  - sql exec took:  1.068186ms
length:  208  - sql exec took:  1.217821ms
length:  209  - sql exec took:  938.338µs
length:  210  - sql exec took:  1.113587ms
length:  211  - sql exec took:  960.558µs
length:  212  - sql exec took:  1.128109ms
length:  213  - sql exec took:  928.162µs
length:  214  - sql exec took:  1.271289ms
length:  215  - sql exec took:  957.65µs
length:  216  - sql exec took:  1.099575ms
length:  217  - sql exec took:  1.024809ms
length:  218  - sql exec took:  1.32355ms
length:  219  - sql exec took:  974.058µs
length:  220  - sql exec took:  1.103869ms
length:  221  - sql exec took:  982.884µs
length:  222  - sql exec took:  1.272344ms
length:  223  - sql exec took:  948.283µs
length:  224  - sql exec took:  1.085522ms
length:  225  - sql exec took:  963.489µs
length:  226  - sql exec took:  1.248108ms
length:  227  - sql exec took:  945.93µs
length:  228  - sql exec took:  1.174482ms
length:  229  - sql exec took:  935.52µs
length:  230  - sql exec took:  1.458825ms
length:  231  - sql exec took:  1.150586ms
length:  232  - sql exec took:  1.388772ms
length:  233  - sql exec took:  1.005541ms
length:  234  - sql exec took:  1.217354ms
length:  235  - sql exec took:  1.032087ms
length:  236  - sql exec took:  1.426521ms
length:  237  - sql exec took:  999.081µs
length:  238  - sql exec took:  1.200478ms
length:  239  - sql exec took:  1.052051ms
length:  240  - sql exec took:  1.255109ms
length:  241  - sql exec took:  1.020972ms
length:  242  - sql exec took:  1.477813ms
length:  243  - sql exec took:  1.03809ms
length:  244  - sql exec took:  1.199034ms
length:  245  - sql exec took:  1.017886ms
panic: runtime error: slice bounds out of range [-97:]

goroutine 1 [running]:
github.com/sijms/go-ora/v2/network.(*Session).GetInt64(0xc000092a80?, 0x1?, 0x0?, 0x0?)
sijms commented 2 months ago

I fix it in last commit but I should test the issue also as input parameters

rfoh commented 2 months ago

Thanks @sijms!!!

sijms commented 2 months ago

fixed also for input parameters

sijms commented 2 months ago

fixed in v2.8.17