Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting subscript index of cstring is allowed and generates bad code #14157

Open
metagn opened this issue Apr 29, 2020 · 15 comments
Open

Setting subscript index of cstring is allowed and generates bad code #14157

metagn opened this issue Apr 29, 2020 · 15 comments
Labels
Invalid Code Acceptance Everything related to compiler not complaining about invalid code Javascript

Comments

@metagn
Copy link
Collaborator

metagn commented Apr 29, 2020

Low priority, disallowing this makes more sense than making it work.

Example

var x = cstring"abcd"
x[0] = 'x'

Current Output

x_43003[0].charCodeAt(0) = 97;
^

ReferenceError: Invalid left-hand side in assignment

Expected Output

compile error

Possible Solution

  • undefine []= for cstring in JS. Or leave it alone and let people get the error on their own. relevant definition:

Nim/lib/system.nim

Lines 437 to 438 in dc3919b

proc `[]=`*[I: Ordinal;T,S](a: T; i: I;
x: sink S) {.noSideEffect, magic: "ArrPut".}

$ nim -v
Nim Compiler Version 1.3.1
@metagn metagn changed the title JS: setting index of cstring is allowed and generates bad codegen JS: setting subscript index of cstring is allowed and generates bad code Apr 29, 2020
@ghost ghost added the Javascript label Oct 19, 2020
@ghost
Copy link

ghost commented Oct 19, 2020

Just FYI - this is not specific to the JS backend :)

@ghost ghost added Invalid Code Acceptance Everything related to compiler not complaining about invalid code and removed Javascript labels Oct 19, 2020
@ghost ghost changed the title JS: setting subscript index of cstring is allowed and generates bad code Setting subscript index of cstring is allowed and generates bad code Oct 19, 2020
@ringabout
Copy link
Member

bad code gen at both C and JS banckend.
Works in VM at both C and JS banckend.

I think we should disable it in code gen phase

@timotheecour
Copy link
Member

timotheecour commented Nov 7, 2020

For c, see another issue (search sigbus), it leads to bad code only in specific cases so disabling it for c in all cases is not good. It's a complicated issue, but theres a way to solve it.

@ringabout
Copy link
Member

ringabout commented Nov 7, 2020

Could you give me an example?

cstring is char * in c backend, it seems not to be modified?
https://stackoverflow.com/questions/1011455/is-it-possible-to-modify-a-string-of-char-in-c

At least it fails in the simple example above.

Edited:
foud the sigbus issue and link it:
#8463

ringabout added a commit to ringabout/Nim that referenced this issue Nov 7, 2020
@ringabout
Copy link
Member

ringabout commented Nov 7, 2020

Anyway, we should document this situation. Whether this is already documented?

@ringabout
Copy link
Member

ringabout commented Nov 7, 2020

Let's suppose that c part won't be fixed like #8463 said or we could document c part. Because c part is only specific to cstring literals modification.

This works in c backend not in JS backend.

var x = "123456"
var s: cstring = x
s[0] = 'u'

I will label this issue as JS.

ringabout added a commit to ringabout/Nim that referenced this issue Nov 7, 2020
ringabout added a commit to ringabout/Nim that referenced this issue Nov 7, 2020
@timotheecour
Copy link
Member

timotheecour commented Nov 7, 2020

for js it should be statically disallowed, that's simple.

for c, there are 2 solutions:

@Araq
Copy link
Member

Araq commented Nov 9, 2020

There should be no []= accessor for cstring at all.

@ringabout
Copy link
Member

I try to undefine []= for cstring, but it doesn't work. I'm not sure it caused by magic.

proc `[]=`*[I: Ordinal;T: not cstring,S](a: T; i: I; 
   x: sink S) {.noSideEffect, magic: "ArrPut".} 

Overload [] doesn't work too

import system except `[]=`


proc `[]=`(x: cstring, index: int, c: string) =
  echo "Hui"

var wind = cstring"abcd"
wind[0] = "1234"

@timotheecour
Copy link
Member

timotheecour commented Nov 9, 2020

There should be no []= accessor for cstring at all.

that'd be a large breaking change:

proc main()=
  var a = "foo"
  var b: cstring = a # or getting `b` from C API that returns a `char*` (not a `const char*`)
  b[0] = 'F'
  echo a
main()

fusion/pointers can add an overload

  proc toUncheckedArray*(a: cstring): ptr UncheckedArray[char] {.inline.} =
    cast[ptr UncheckedArray[char]](a)

to mitigate (and keep this 0 cost) but still.

note

even if we add this toUncheckedArray overload (which seems useful regardless), cstring.[]= can be made safer than UncheckedArray.[]= using a new cstringChecks as follows:

proc `[]=`(a: cstring, b: index) =
  when compileOption("cstringChecks):
    doAssert b < a.len
  #rest of code

ditto with [].

Whereas this wouldn't be possible with UncheckedArray, which shouldn't be concerned with 0-terminated C strings.

So cstring.[]= is more typesafe than UncheckedArray[char].[]=

@ringabout ringabout mentioned this issue Nov 11, 2020
@Araq Araq closed this as completed in 1f9bf43 Nov 12, 2020
Araq added a commit that referenced this issue Nov 12, 2020
… allowed (#15878)

* follow #8463 #14157 and document cstring literals
* Update doc/manual.rst

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
narimiran pushed a commit that referenced this issue Nov 16, 2020
* fix #14157

* Update compiler/jsgen.nim

* add changelog

* Update compiler/jsgen.nim

* Update tests/js/tmodify_cstring.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 1f9bf43)
PMunch pushed a commit to PMunch/Nim that referenced this issue Jan 6, 2021
* fix nim-lang#14157

* Update compiler/jsgen.nim

* add changelog

* Update compiler/jsgen.nim

* Update tests/js/tmodify_cstring.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
PMunch pushed a commit to PMunch/Nim that referenced this issue Jan 6, 2021
…ification is not allowed (nim-lang#15878)

* follow nim-lang#8463 nim-lang#14157 and document cstring literals
* Update doc/manual.rst

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
mildred pushed a commit to mildred/Nim that referenced this issue Jan 11, 2021
* fix nim-lang#14157

* Update compiler/jsgen.nim

* add changelog

* Update compiler/jsgen.nim

* Update tests/js/tmodify_cstring.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
mildred pushed a commit to mildred/Nim that referenced this issue Jan 11, 2021
…ification is not allowed (nim-lang#15878)

* follow nim-lang#8463 nim-lang#14157 and document cstring literals
* Update doc/manual.rst

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
@timotheecour timotheecour reopened this Feb 1, 2021
@timotheecour
Copy link
Member

timotheecour commented Feb 1, 2021

@xflywind IMO #15877 is not the right fix not sufficient, see here:

proc main()=
  var a = "abc".cstring
  template fn() =
    a[0] = 'x'
  # fn() # ok: correctly gives: Error: cstring doesn't support `[]=` operator
  doAssert not compiles(fn()) # bug: assert fails
main()

nim r -b:js main fails (eef2948 1.5.1)

IMO the right fix should happen "earlier", we need to look deeper into #15877 (comment)

see also: #15911

@ringabout
Copy link
Member

ringabout commented Feb 1, 2021

It seems to compile

static:
  var a = "abc".cstring
  template fn() =
    a[0] = 'x'
  fn()

@timotheecour
Copy link
Member

[]= should be legal in VM+js but not in RT+js; it's a similar problem as the cross compiling issue in #16702 (comment) .

I don't know if this is solvable or not TBH.

proc main1() =
  var a = "abc"
  var b = a.cstring
  b[0] = 'x'
  template fn() = b[0] = 'x'
  doAssert compiles(fn())

proc main2()=
  var a = "abc"
  var b = a.cstring
  # b[0] = 'x' # correctly gives: Error: cstring doesn't support `[]=` operator
  doAssert not compiles(fn()) # should succeed, but right now fails
  when compiles(fn()):
    echo "foo" # should this print or not?

static: main1()
main2()

@ringabout
Copy link
Member

bad code gen at both C and JS banckend.
Works in VM at both C and JS banckend.

I think we should disable it in code gen phase

My PR just fix the JS code gen.

@timotheecour
Copy link
Member

I'm thinking of the following general approach to solve this kind of problem (refs timotheecour#564):

when defined(js):
  proc `[]=`*(a: cstring, b: int, c: char) {.nimvm.} = ... 
else:
  proc `[]=`*(a: cstring, b: int, c: char) = ... 

in this example, you'd have this behavior:

  • in c backend, []= would be defined (for rt or vm)
  • in js backend, []= would be defined if we're in vm, but not if we're in js

there are other use cases of {.nimvm.} which adds some notion of namespacing to distinguish whether we're running in vm or rt.

irdassis pushed a commit to irdassis/Nim that referenced this issue Mar 16, 2021
* fix nim-lang#14157

* Update compiler/jsgen.nim

* add changelog

* Update compiler/jsgen.nim

* Update tests/js/tmodify_cstring.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
irdassis pushed a commit to irdassis/Nim that referenced this issue Mar 16, 2021
…ification is not allowed (nim-lang#15878)

* follow nim-lang#8463 nim-lang#14157 and document cstring literals
* Update doc/manual.rst

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
ardek66 pushed a commit to ardek66/Nim that referenced this issue Mar 26, 2021
* fix nim-lang#14157

* Update compiler/jsgen.nim

* add changelog

* Update compiler/jsgen.nim

* Update tests/js/tmodify_cstring.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
ardek66 pushed a commit to ardek66/Nim that referenced this issue Mar 26, 2021
…ification is not allowed (nim-lang#15878)

* follow nim-lang#8463 nim-lang#14157 and document cstring literals
* Update doc/manual.rst

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Invalid Code Acceptance Everything related to compiler not complaining about invalid code Javascript
Projects
None yet
Development

No branches or pull requests

4 participants