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

Construct Vector without an invalid internal state #8246

Closed
wants to merge 1 commit into from
Closed

Construct Vector without an invalid internal state #8246

wants to merge 1 commit into from

Conversation

Jin-H
Copy link
Contributor

@Jin-H Jin-H commented Jul 18, 2019

when i debug vector's add behavior, i found out the reason why scala throw NPE is because the value of variable newFocus is negative. So accordingly, the code judges its depth is 0(the actual depth should be 2), which lead to a incorrect start position.

    //Vector.scala method appended() line 501
    val s = new Vector(startIndex - shift, endIndex + 1 - shift, newBlockIndex)
    s.initFrom(this)
    s.dirty = dirty
    s.shiftTopLevel(shiftBlocks, 0) // shift left by n blocks
    //which result this problem
    s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex)
    s.display0(lo) = value.asInstanceOf[AnyRef]

Thus i think the value of newFocus should be positive all the time, we only need to pay attention to its absolute value

Fixes scala/bug#11636

@scala-jenkins scala-jenkins added this to the 2.13.1 milestone Jul 18, 2019
@Ichoran
Copy link
Contributor

Ichoran commented Jul 18, 2019

I'm quite worried that this would mask an underlying logic error rather than just fix the NPE. Why should the absolute value accurately describe what to do?

@diesalbla diesalbla added library:collections PRs involving changes to the standard collection library bug fix labels Jul 18, 2019
@Jin-H Jin-H marked this pull request as ready for review July 19, 2019 00:26
@Jin-H
Copy link
Contributor Author

Jin-H commented Jul 20, 2019

I am sorry to reply so late. The following is my opinion.

newBlockIndex 
= blockIndex - shift
= (endIndex & ~31) - (startIndex & ~((1 << (5 * (depth - 1))) - 1)) 
>= (endIndex & ~31) - (startIndex & ~31) > 0
//when depth == 2 
= (endIndex & ~31) - (startIndex & ~31)
//when depth > 2
> (endIndex & ~31) - (startIndex & ~31)

newFocus
= focus - shift
= focus - (startIndex & ~((1 << (5 * (depth - 1))) - 1)) 

then

s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex)

the value of newFocus ^ newBlockIndex just standard for the level, so I guess it should be positive.

def gotoFreshPosWritable0(oldIndex: Int, newIndex: Int, xor: Int): Unit = { // goto block start pos
      if        (xor < (1 <<  5)) { // level = 0
        // we're already at the block start
      } else if (xor < (1 << 10)) { // level = 1
       // ...
      } else if (xor < (1 << 15)) { // level = 2
       
      }
      //....
}

the following test case works well, and the ++ operator go through the same branch, and the value of variable newFocus is positive. I also know it will be just a coincidence.

@Test
  def constructProperStartIndex(): Unit = {
    val a = "A1" +: "A" +: "O" +: Iterator.continually("E").take(2078).foldLeft(Vector.empty[String])((v, e) => v :+ e) :+ "C" :+"C"
    val d = "O" +: Iterator.continually("E").take(0)   .foldLeft(Vector.empty[String])((v, e) => v :+ e) :+ "C"
    val right = a ++ d

    assertEquals(2085, right.map(_ => 0).size)
  }

ahh, could you give me some suggestions? @Ichoran

@SethTisue SethTisue added the prio:blocker release blocker (used only by core team, only near release time) label Sep 9, 2019
@szeiger
Copy link
Member

szeiger commented Sep 9, 2019

@Ichoran can you take a look?

@szeiger szeiger added the release-notes worth highlighting in next release notes label Sep 9, 2019
@Ichoran
Copy link
Contributor

Ichoran commented Sep 9, 2019

@szeiger - Unfortunately I'm incredibly busy through the end of the month. Was it @joshlemer who had worked on Vector recently? (Is this already fixed by some other PR? I thought i saw something come through that addressed Vector soundness issues.)

@SethTisue SethTisue changed the title Fixes scala/bug#11636 Fix bug (scala/bug#11636) where Vector can be constructed with an invalid internal state Sep 9, 2019
@joshlemer
Copy link
Member

@Ichoran yes it was me who last touched Vector code and that probably caused this bug.

The error is almost certainly somewhere in here:
#7743

I am trying to figure out what the error is but it is quite tricky...

@joshlemer
Copy link
Member

It may be best to just revert that PR for now, since that one was also responsible for this bug: scala/bug#11600 though that one has existing fixes up for consideration.

@joshlemer
Copy link
Member

joshlemer commented Sep 9, 2019

Strike that, update: the bug is not in that commit, the bug has something to do with these changes: #7588

(When I revert that change, the bug is gone)

Update: Yeah, the VectorBuilder changes in that commit are not quite right somehow, that's definitely the issue.

@szeiger
Copy link
Member

szeiger commented Sep 10, 2019

I opened #8410 to revert the VectorBuilder optimization for now. Rescheduling this PR to 2.13.2 to give us some more time to get it right.

@szeiger szeiger modified the milestones: 2.13.1, 2.13.2 Sep 10, 2019
@szeiger szeiger removed the prio:blocker release blocker (used only by core team, only near release time) label Sep 10, 2019
@SethTisue
Copy link
Member

SethTisue commented Feb 6, 2020

@szeiger this seems like a fix that really ought to make 2.13.2 if possible

that is, if we don't end up replacing Vector entirely: #8534

leaving it on the 2.13.2 milestone for now

@dwijnand dwijnand changed the title Fix bug (scala/bug#11636) where Vector can be constructed with an invalid internal state Construct Vector without an invalid internal state Feb 13, 2020
@lrytz
Copy link
Member

lrytz commented Mar 18, 2020

@szeiger should this PR be re-targeted at 2.12.x?

@joshlemer
Copy link
Member

@lrytz so far as I understand, this is only a bug fix meant to address bugs that appeared in 2.13.0

@SethTisue
Copy link
Member

obviated by #8534

@SethTisue SethTisue closed this Mar 18, 2020
@SethTisue SethTisue removed this from the 2.13.2 milestone Mar 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
library:collections PRs involving changes to the standard collection library release-notes worth highlighting in next release notes
Projects
None yet
8 participants